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:
parent
9736123483
commit
3a67cc2c45
|
@ -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
|
|
@ -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))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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"`
|
|
@ -1,6 +1,6 @@
|
||||||
// +build darwin
|
// +build darwin
|
||||||
|
|
||||||
package sysutil
|
package aghnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
|
@ -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")
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package sysutil
|
package aghnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
|
@ -1,6 +1,6 @@
|
||||||
// +build !linux,!darwin
|
// +build !linux,!darwin
|
||||||
|
|
||||||
package sysutil
|
package aghnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -1,4 +1,4 @@
|
||||||
package util
|
package aghnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -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"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// +build freebsd
|
// +build freebsd
|
||||||
|
|
||||||
package sysutil
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
|
@ -1,6 +1,6 @@
|
||||||
// +build linux
|
// +build linux
|
||||||
|
|
||||||
package sysutil
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
|
@ -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"
|
|
@ -1,6 +1,6 @@
|
||||||
// +build windows
|
// +build windows
|
||||||
|
|
||||||
package sysutil
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
|
@ -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 {
|
|
@ -1,6 +1,6 @@
|
||||||
// +build !windows,!plan9
|
// +build !windows,!plan9
|
||||||
|
|
||||||
package sysutil
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log/syslog"
|
"log/syslog"
|
|
@ -1,6 +1,6 @@
|
||||||
// +build windows plan9
|
// +build windows plan9
|
||||||
|
|
||||||
package sysutil
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
|
@ -1,4 +1,4 @@
|
||||||
package sysutil
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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])
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
Loading…
Reference in New Issue