Pull request: create aghnet package

Merge in DNS/adguard-home from mk-aghnet to master

Updates #2829.

Squashed commit of the following:

commit 519806c04b8d0517aacce9c31f2d06ab56631937
Merge: 92376c86 97361234
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Mar 16 19:13:56 2021 +0300

    Merge branch 'master' into mk-aghnet

commit 92376c8665e529191aa482432f9d5e3e2e3afdc8
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Mar 16 18:37:22 2021 +0300

    aghnet: fix linux

commit 7f36d19b0e650d4e4fc5cf9ea4b501a7f636abeb
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Mar 16 18:08:30 2021 +0300

    aghnet: mv network utils from util

commit aa68c70c1146b8c32303c6e037953a41aa7d72f9
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Mar 16 17:30:06 2021 +0300

    aghnet: mv ipDetector here

commit b033657f5c5ee91f869c36508a5eb15976a174a0
Author: Eugene Burkov <e.burkov@adguard.com>
Date:   Tue Mar 16 17:24:07 2021 +0300

    all: mk aghnet package, rename sysutil package
This commit is contained in:
Eugene Burkov 2021-03-16 19:42:15 +03:00
parent 9736123483
commit 3a67cc2c45
26 changed files with 135 additions and 148 deletions

View File

@ -1,14 +1,14 @@
package home package aghnet
import "net" import "net"
// ipDetector describes IP address properties. // IPDetector describes IP address properties.
type ipDetector struct { type IPDetector struct {
nets []*net.IPNet nets []*net.IPNet
} }
// newIPDetector returns a new IP detector. // NewIPDetector returns a new IP detector.
func newIPDetector() (ipd *ipDetector, err error) { func NewIPDetector() (ipd *IPDetector, err error) {
specialNetworks := []string{ specialNetworks := []string{
"0.0.0.0/8", "0.0.0.0/8",
"10.0.0.0/8", "10.0.0.0/8",
@ -43,7 +43,7 @@ func newIPDetector() (ipd *ipDetector, err error) {
"fe80::/10", "fe80::/10",
} }
ipd = &ipDetector{ ipd = &IPDetector{
nets: make([]*net.IPNet, len(specialNetworks)), nets: make([]*net.IPNet, len(specialNetworks)),
} }
for i, ipnetStr := range specialNetworks { for i, ipnetStr := range specialNetworks {
@ -59,10 +59,10 @@ func newIPDetector() (ipd *ipDetector, err error) {
return ipd, nil 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 // special-purpose IP address registries according to RFC-6890
// (https://tools.ietf.org/html/rfc6890). // (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 { for _, ipnet := range ipd.nets {
if ipnet.Contains(ip) { if ipnet.Contains(ip) {
return true return true

View File

@ -1,4 +1,4 @@
package home package aghnet
import ( import (
"net" "net"
@ -9,10 +9,10 @@ import (
) )
func TestIPDetector_detectSpecialNetwork(t *testing.T) { func TestIPDetector_detectSpecialNetwork(t *testing.T) {
var ipd *ipDetector var ipd *IPDetector
var err error var err error
ipd, err = newIPDetector() ipd, err = NewIPDetector()
require.Nil(t, err) require.Nil(t, err)
testCases := []struct { testCases := []struct {
@ -139,7 +139,7 @@ func TestIPDetector_detectSpecialNetwork(t *testing.T) {
for _, tc := range testCases { for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) { 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))
}) })
} }
} }

View File

@ -1,4 +1,5 @@
package util // Package aghnet contains some utilities for networking.
package aghnet
import ( import (
"encoding/json" "encoding/json"
@ -6,14 +7,70 @@ import (
"fmt" "fmt"
"net" "net"
"os" "os"
"os/exec"
"runtime" "runtime"
"strconv" "strconv"
"strings"
"syscall" "syscall"
"time" "time"
"github.com/AdguardTeam/AdGuardHome/internal/agherr"
"github.com/AdguardTeam/golibs/log" "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. // NetInterface represents an entry of network interfaces map.
type NetInterface struct { type NetInterface struct {
MTU int `json:"mtu"` MTU int `json:"mtu"`

View File

@ -1,6 +1,6 @@
// +build darwin // +build darwin
package sysutil package aghnet
import ( import (
"errors" "errors"

View File

@ -1,6 +1,6 @@
// +build linux // +build linux
package sysutil package aghnet
import ( import (
"bufio" "bufio"
@ -13,7 +13,6 @@ import (
"strings" "strings"
"github.com/AdguardTeam/AdGuardHome/internal/aghio" "github.com/AdguardTeam/AdGuardHome/internal/aghio"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/golibs/file" "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) { func ifaceSetStaticIP(ifaceName string) (err error) {
ipNet := util.GetSubnet(ifaceName) ipNet := GetSubnet(ifaceName)
if ipNet.IP == nil { if ipNet.IP == nil {
return errors.New("can't get IP address") return errors.New("can't get IP address")
} }

View File

@ -1,6 +1,6 @@
// +build linux // +build linux
package sysutil package aghnet
import ( import (
"bytes" "bytes"

View File

@ -1,6 +1,6 @@
// +build !linux,!darwin // +build !linux,!darwin
package sysutil package aghnet
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package util package aghnet
import ( import (
"testing" "testing"

View File

@ -1,5 +1,5 @@
// Package sysutil contains utilities for functions requiring system calls. // Package aghos contains utilities for functions requiring system calls.
package sysutil package aghos
import "syscall" import "syscall"

View File

@ -1,6 +1,6 @@
// +build freebsd // +build freebsd
package sysutil package aghos
import ( import (
"os" "os"

View File

@ -1,6 +1,6 @@
// +build linux // +build linux
package sysutil package aghos
import ( import (
"os" "os"

View File

@ -1,6 +1,6 @@
// +build aix darwin dragonfly netbsd openbsd solaris // +build aix darwin dragonfly netbsd openbsd solaris
package sysutil package aghos
import ( import (
"os" "os"

View File

@ -1,6 +1,6 @@
// +build windows // +build windows
package sysutil package aghos
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package sysutil package aghos
// ConfigureSyslog reroutes standard logger output to syslog. // ConfigureSyslog reroutes standard logger output to syslog.
func ConfigureSyslog(serviceName string) error { func ConfigureSyslog(serviceName string) error {

View File

@ -1,6 +1,6 @@
// +build !windows,!plan9 // +build !windows,!plan9
package sysutil package aghos
import ( import (
"log/syslog" "log/syslog"

View File

@ -1,6 +1,6 @@
// +build windows plan9 // +build windows plan9
package sysutil package aghos
import ( import (
"strings" "strings"

View File

@ -1,4 +1,4 @@
package sysutil package aghos
import ( import (
"testing" "testing"

View File

@ -10,8 +10,7 @@ import (
"os" "os"
"strings" "strings"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil" "github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/golibs/log" "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) { func (s *Server) enableDHCP(ifaceName string) (code int, err error) {
var hasStaticIP bool var hasStaticIP bool
hasStaticIP, err = sysutil.IfaceHasStaticIP(ifaceName) hasStaticIP, err = aghnet.IfaceHasStaticIP(ifaceName)
if err != nil { if err != nil {
if errors.Is(err, os.ErrPermission) { if errors.Is(err, os.ErrPermission) {
// ErrPermission may happen here on Linux systems where // 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; "+ log.Info("error while checking static ip: %s; "+
"assuming machine has static ip and going on", err) "assuming machine has static ip and going on", err)
hasStaticIP = true hasStaticIP = true
} else if errors.Is(err, sysutil.ErrNoStaticIPInfo) { } else if errors.Is(err, aghnet.ErrNoStaticIPInfo) {
// Couldn't obtain a definitive answer. Assume static // Couldn't obtain a definitive answer. Assume static
// IP an go on. // IP an go on.
log.Info("can't check for static ip; " + log.Info("can't check for static ip; " +
@ -124,7 +123,7 @@ func (s *Server) enableDHCP(ifaceName string) (code int, err error) {
} }
if !hasStaticIP { if !hasStaticIP {
err = sysutil.IfaceSetStaticIP(ifaceName) err = aghnet.IfaceSetStaticIP(ifaceName)
if err != nil { if err != nil {
err = fmt.Errorf("setting static ip: %w", err) 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) { func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) {
response := map[string]netInterfaceJSON{} response := map[string]netInterfaceJSON{}
ifaces, err := util.GetValidNetInterfaces() ifaces, err := aghnet.GetValidNetInterfaces()
if err != nil { if err != nil {
httpError(r, w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err) httpError(r, w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err)
return return
@ -317,7 +316,7 @@ func (s *Server) handleDHCPInterfaces(w http.ResponseWriter, r *http.Request) {
} }
} }
if len(jsonIface.Addrs4)+len(jsonIface.Addrs6) != 0 { if len(jsonIface.Addrs4)+len(jsonIface.Addrs6) != 0 {
jsonIface.GatewayIP = sysutil.GatewayIP(iface.Name) jsonIface.GatewayIP = aghnet.GatewayIP(iface.Name)
response[iface.Name] = jsonIface response[iface.Name] = jsonIface
} }
} }
@ -397,13 +396,13 @@ func (s *Server) handleDHCPFindActiveServer(w http.ResponseWriter, r *http.Reque
found4, err4 := CheckIfOtherDHCPServersPresentV4(interfaceName) found4, err4 := CheckIfOtherDHCPServersPresentV4(interfaceName)
isStaticIP, err := sysutil.IfaceHasStaticIP(interfaceName) isStaticIP, err := aghnet.IfaceHasStaticIP(interfaceName)
if err != nil { if err != nil {
result.V4.StaticIP.Static = "error" result.V4.StaticIP.Static = "error"
result.V4.StaticIP.Error = err.Error() result.V4.StaticIP.Error = err.Error()
} else if !isStaticIP { } else if !isStaticIP {
result.V4.StaticIP.Static = "no" result.V4.StaticIP.Static = "no"
result.V4.StaticIP.IP = util.GetSubnet(interfaceName).String() result.V4.StaticIP.IP = aghnet.GetSubnet(interfaceName).String()
} }
if found4 { if found4 {

View File

@ -15,9 +15,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
) )
@ -26,7 +24,7 @@ import (
type getAddrsResponse struct { type getAddrsResponse struct {
WebPort int `json:"web_port"` WebPort int `json:"web_port"`
DNSPort int `json:"dns_port"` DNSPort int `json:"dns_port"`
Interfaces map[string]*util.NetInterface `json:"interfaces"` Interfaces map[string]*aghnet.NetInterface `json:"interfaces"`
} }
// handleInstallGetAddresses is the handler for /install/get_addresses endpoint. // 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.WebPort = 80
data.DNSPort = 53 data.DNSPort = 53
ifaces, err := util.GetValidNetInterfacesForWeb() ifaces, err := aghnet.GetValidNetInterfacesForWeb()
if err != nil { if err != nil {
httpError(w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err) httpError(w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err)
return return
} }
data.Interfaces = make(map[string]*util.NetInterface) data.Interfaces = make(map[string]*aghnet.NetInterface)
for _, iface := range ifaces { for _, iface := range ifaces {
data.Interfaces[iface.Name] = iface 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 { 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 { if err != nil {
respData.Web.Status = err.Error() respData.Web.Status = err.Error()
} }
} }
if reqData.DNS.Port != 0 { 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() canAutofix := checkDNSStubListener()
if canAutofix && reqData.DNS.Autofix { 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) 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 canAutofix = false
} }
@ -120,7 +118,7 @@ func (web *Web) handleInstallCheckConfig(w http.ResponseWriter, r *http.Request)
} }
if err == nil { if err == nil {
err = util.CheckPortAvailable(reqData.DNS.IP, reqData.DNS.Port) err = aghnet.CheckPortAvailable(reqData.DNS.IP, reqData.DNS.Port)
} }
if err != nil { 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 { func handleStaticIP(ip net.IP, set bool) staticIPJSON {
resp := staticIPJSON{} resp := staticIPJSON{}
interfaceName := util.GetInterfaceByIP(ip) interfaceName := aghnet.GetInterfaceByIP(ip)
resp.Static = "no" resp.Static = "no"
if len(interfaceName) == 0 { if len(interfaceName) == 0 {
@ -155,7 +153,7 @@ func handleStaticIP(ip net.IP, set bool) staticIPJSON {
if set { if set {
// Try to set static IP for the specified interface // Try to set static IP for the specified interface
err := sysutil.IfaceSetStaticIP(interfaceName) err := aghnet.IfaceSetStaticIP(interfaceName)
if err != nil { if err != nil {
resp.Static = "error" resp.Static = "error"
resp.Error = err.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 // Fallthrough here even if we set static IP
// Check if we have a static IP and return the details // Check if we have a static IP and return the details
isStaticIP, err := sysutil.IfaceHasStaticIP(interfaceName) isStaticIP, err := aghnet.IfaceHasStaticIP(interfaceName)
if err != nil { if err != nil {
resp.Static = "error" resp.Static = "error"
resp.Error = err.Error() resp.Error = err.Error()
@ -173,7 +171,7 @@ func handleStaticIP(ip net.IP, set bool) staticIPJSON {
if isStaticIP { if isStaticIP {
resp.Static = "yes" resp.Static = "yes"
} }
resp.IP = util.GetSubnet(interfaceName).String() resp.IP = aghnet.GetSubnet(interfaceName).String()
} }
return resp return resp
} }
@ -315,7 +313,7 @@ func (web *Web) handleInstallConfigure(w http.ResponseWriter, r *http.Request) {
// validate that hosts and ports are bindable // validate that hosts and ports are bindable
if restartHTTP { if restartHTTP {
err = util.CheckPortAvailable(newSettings.Web.IP, newSettings.Web.Port) err = aghnet.CheckPortAvailable(newSettings.Web.IP, newSettings.Web.Port)
if err != nil { if err != nil {
httpError(w, http.StatusBadRequest, "Impossible to listen on IP:port %s due to %s", 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) 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 { if err != nil {
httpError(w, http.StatusBadRequest, "%s", err) httpError(w, http.StatusBadRequest, "%s", err)
return return
} }
err = util.CheckPortAvailable(newSettings.DNS.IP, newSettings.DNS.Port) err = aghnet.CheckPortAvailable(newSettings.DNS.IP, newSettings.DNS.Port)
if err != nil { if err != nil {
httpError(w, http.StatusBadRequest, "%s", err) httpError(w, http.StatusBadRequest, "%s", err)
return return
@ -539,7 +537,7 @@ func (web *Web) handleInstallConfigureBeta(w http.ResponseWriter, r *http.Reques
type getAddrsResponseBeta struct { type getAddrsResponseBeta struct {
WebPort int `json:"web_port"` WebPort int `json:"web_port"`
DNSPort int `json:"dns_port"` DNSPort int `json:"dns_port"`
Interfaces []*util.NetInterface `json:"interfaces"` Interfaces []*aghnet.NetInterface `json:"interfaces"`
} }
// handleInstallConfigureBeta is a substitution of /install/get_addresses // 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.WebPort = 80
data.DNSPort = 53 data.DNSPort = 53
ifaces, err := util.GetValidNetInterfacesForWeb() ifaces, err := aghnet.GetValidNetInterfacesForWeb()
if err != nil { if err != nil {
httpError(w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err) httpError(w, http.StatusInternalServerError, "Couldn't get interfaces: %s", err)
return return

View File

@ -12,7 +12,7 @@ import (
"syscall" "syscall"
"time" "time"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil" "github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/AdGuardHome/internal/updater" "github.com/AdguardTeam/AdGuardHome/internal/updater"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
) )
@ -141,7 +141,7 @@ func (vr *versionResponse) confirmAutoUpdate() {
tlsConf.PortDNSOverQUIC < 1024)) || tlsConf.PortDNSOverQUIC < 1024)) ||
config.BindPort < 1024 || config.BindPort < 1024 ||
config.DNS.Port < 1024) { config.DNS.Port < 1024) {
canUpdate, _ = sysutil.CanBindPrivilegedPorts() canUpdate, _ = aghos.CanBindPrivilegedPorts()
} }
vr.CanAutoUpdate = &canUpdate vr.CanAutoUpdate = &canUpdate
} }

View File

@ -9,11 +9,11 @@ import (
"strconv" "strconv"
"github.com/AdguardTeam/AdGuardHome/internal/agherr" "github.com/AdguardTeam/AdGuardHome/internal/agherr"
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/AdGuardHome/internal/dnsfilter" "github.com/AdguardTeam/AdGuardHome/internal/dnsfilter"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward" "github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/querylog" "github.com/AdguardTeam/AdGuardHome/internal/querylog"
"github.com/AdguardTeam/AdGuardHome/internal/stats" "github.com/AdguardTeam/AdGuardHome/internal/stats"
"github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/proxy"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/ameshkov/dnscrypt/v2" "github.com/ameshkov/dnscrypt/v2"
@ -109,7 +109,7 @@ func onDNSRequest(d *proxy.DNSContext) {
if !ip.IsLoopback() { if !ip.IsLoopback() {
Context.rdns.Begin(ip) Context.rdns.Begin(ip)
} }
if !Context.ipDetector.detectSpecialNetwork(ip) { if !Context.ipDetector.DetectSpecialNetwork(ip) {
Context.whois.Begin(ip) Context.whois.Begin(ip)
} }
} }
@ -253,7 +253,7 @@ func getDNSAddresses() []string {
dnsAddresses := []string{} dnsAddresses := []string{}
if config.DNS.BindHost.IsUnspecified() { if config.DNS.BindHost.IsUnspecified() {
ifaces, e := util.GetValidNetInterfacesForWeb() ifaces, e := aghnet.GetValidNetInterfacesForWeb()
if e != nil { if e != nil {
log.Error("Couldn't get network interfaces: %v", e) log.Error("Couldn't get network interfaces: %v", e)
return []string{} return []string{}
@ -344,7 +344,7 @@ func startDNSServer() error {
if !ip.IsLoopback() { if !ip.IsLoopback() {
Context.rdns.Begin(ip) Context.rdns.Begin(ip)
} }
if !Context.ipDetector.detectSpecialNetwork(ip) { if !Context.ipDetector.DetectSpecialNetwork(ip) {
Context.whois.Begin(ip) Context.whois.Begin(ip)
} }
} }

View File

@ -22,12 +22,13 @@ import (
"time" "time"
"github.com/AdguardTeam/AdGuardHome/internal/agherr" "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/dhcpd"
"github.com/AdguardTeam/AdGuardHome/internal/dnsfilter" "github.com/AdguardTeam/AdGuardHome/internal/dnsfilter"
"github.com/AdguardTeam/AdGuardHome/internal/dnsforward" "github.com/AdguardTeam/AdGuardHome/internal/dnsforward"
"github.com/AdguardTeam/AdGuardHome/internal/querylog" "github.com/AdguardTeam/AdGuardHome/internal/querylog"
"github.com/AdguardTeam/AdGuardHome/internal/stats" "github.com/AdguardTeam/AdGuardHome/internal/stats"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil"
"github.com/AdguardTeam/AdGuardHome/internal/updater" "github.com/AdguardTeam/AdGuardHome/internal/updater"
"github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/AdGuardHome/internal/version" "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 autoHosts util.AutoHosts // IP-hostname pairs taken from system configuration (e.g. /etc/hosts) files
updater *updater.Updater updater *updater.Updater
ipDetector *ipDetector ipDetector *aghnet.IPDetector
// mux is our custom http.ServeMux. // mux is our custom http.ServeMux.
mux *http.ServeMux mux *http.ServeMux
@ -204,7 +205,7 @@ func setupConfig(args options) {
if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") && if (runtime.GOOS == "linux" || runtime.GOOS == "darwin") &&
config.RlimitNoFile != 0 { config.RlimitNoFile != 0 {
sysutil.SetRlimit(config.RlimitNoFile) aghos.SetRlimit(config.RlimitNoFile)
} }
// override bind host/port from the console // override bind host/port from the console
@ -304,7 +305,7 @@ func run(args options) {
log.Fatalf("Can't initialize Web module") log.Fatalf("Can't initialize Web module")
} }
Context.ipDetector, err = newIPDetector() Context.ipDetector, err = aghnet.NewIPDetector()
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -361,7 +362,7 @@ func checkPermissions() {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
// On Windows we need to have admin rights to run properly // On Windows we need to have admin rights to run properly
admin, _ := sysutil.HaveAdminRights() admin, _ := aghos.HaveAdminRights()
if admin { if admin {
return return
} }
@ -370,7 +371,7 @@ func checkPermissions() {
} }
// We should check if AdGuard Home is able to bind to port 53 // 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 { if ok {
log.Info("AdGuard Home can bind to port 53") log.Info("AdGuard Home can bind to port 53")
@ -481,7 +482,7 @@ func configureLogger(args options) {
if ls.LogFile == configSyslog { if ls.LogFile == configSyslog {
// Use syslog where it is possible and eventlog on Windows // Use syslog where it is possible and eventlog on Windows
err := sysutil.ConfigureSyslog(serviceName) err := aghos.ConfigureSyslog(serviceName)
if err != nil { if err != nil {
log.Fatalf("cannot initialize syslog: %s", err) log.Fatalf("cannot initialize syslog: %s", err)
} }
@ -592,7 +593,7 @@ func printHTTPAddresses(proto string) {
} }
} else if config.BindHost.IsUnspecified() { } else if config.BindHost.IsUnspecified() {
log.Println("AdGuard Home is available on the following addresses:") log.Println("AdGuard Home is available on the following addresses:")
ifaces, err := util.GetValidNetInterfacesForWeb() ifaces, err := aghnet.GetValidNetInterfacesForWeb()
if err != nil { if err != nil {
// That's weird, but we'll ignore it // That's weird, but we'll ignore it
hostStr = config.BindHost.String() hostStr = config.BindHost.String()

View File

@ -9,7 +9,7 @@ import (
"strings" "strings"
"syscall" "syscall"
"github.com/AdguardTeam/AdGuardHome/internal/sysutil" "github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/AdGuardHome/internal/util"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/kardianos/service" "github.com/kardianos/service"
@ -121,7 +121,7 @@ func sendSigReload() {
log.Error("Can't read PID file %s: %s", pidfile, err) log.Error("Can't read PID file %s: %s", pidfile, err)
return return
} }
err = sysutil.SendProcessSignal(pid, syscall.SIGHUP) err = aghos.SendProcessSignal(pid, syscall.SIGHUP)
if err != nil { if err != nil {
log.Error("Can't send signal to PID %d: %s", pid, err) log.Error("Can't send signal to PID %d: %s", pid, err)
return return

View File

@ -9,7 +9,7 @@ import (
"sync" "sync"
"time" "time"
"github.com/AdguardTeam/AdGuardHome/internal/util" "github.com/AdguardTeam/AdGuardHome/internal/aghnet"
"github.com/AdguardTeam/golibs/log" "github.com/AdguardTeam/golibs/log"
"github.com/NYTimes/gziphandler" "github.com/NYTimes/gziphandler"
"github.com/gobuffalo/packr" "github.com/gobuffalo/packr"
@ -117,7 +117,7 @@ func WebCheckPortAvailable(port int) bool {
alreadyRunning = true alreadyRunning = true
} }
if !alreadyRunning { if !alreadyRunning {
err := util.CheckPortAvailable(config.BindHost, port) err := aghnet.CheckPortAvailable(config.BindHost, port)
if err != nil { if err != nil {
return false return false
} }

View File

@ -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])
}

View File

@ -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
}