cherry-pick: 3157 excessive ptrs

Merge in DNS/adguard-home from 3157-excessive-ptrs to master

Updates #3157.

Squashed commit of the following:

commit 6803988240dca2f147bb80a5b3f78d7749d2fa14
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Apr 19 14:50:01 2022 +0300

    aghnet: and again

commit 1a7f4d1dbc8fd4d3ae620349917526a75fa71b47
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Apr 19 14:49:20 2022 +0300

    aghnet: docs again

commit d88da1fc7135f3cd03aff10b02d9957c8ffdfd30
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Apr 19 14:47:36 2022 +0300

    aghnet: imp docs

commit c45dbc7800e882c6c4110aab640c32b03046f89a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Apr 19 14:41:19 2022 +0300

    aghnet: keep alphabetical order

commit b61781785d096ef43f60fb4f1905a4ed3cdf7c68
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Apr 19 13:50:56 2022 +0300

    aghnet: imp code quality

commit 578dbd71ed2f2089c69343d7d4bf8bbc29150ace
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Apr 12 17:02:38 2022 +0300

    aghnet: imp arp container
This commit is contained in:
Eugene Burkov
2022-04-19 15:01:49 +03:00
committed by Ainar Garipov
parent 723279121a
commit c4a13b92d2
39 changed files with 2111 additions and 510 deletions

View File

@@ -4,10 +4,11 @@
package aghnet
import (
"bufio"
"bytes"
"fmt"
"os"
"io"
"regexp"
"strings"
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/golibs/errors"
@@ -23,7 +24,7 @@ type hardwarePortInfo struct {
static bool
}
func ifaceHasStaticIP(ifaceName string) (bool, error) {
func ifaceHasStaticIP(ifaceName string) (ok bool, err error) {
portInfo, err := getCurrentHardwarePortInfo(ifaceName)
if err != nil {
return false, err
@@ -32,9 +33,10 @@ func ifaceHasStaticIP(ifaceName string) (bool, error) {
return portInfo.static, nil
}
// getCurrentHardwarePortInfo gets information for the specified network interface.
// getCurrentHardwarePortInfo gets information for the specified network
// interface.
func getCurrentHardwarePortInfo(ifaceName string) (hardwarePortInfo, error) {
// First of all we should find hardware port name
// First of all we should find hardware port name.
m := getNetworkSetupHardwareReports()
hardwarePort, ok := m[ifaceName]
if !ok {
@@ -44,6 +46,10 @@ func getCurrentHardwarePortInfo(ifaceName string) (hardwarePortInfo, error) {
return getHardwarePortInfo(hardwarePort)
}
// hardwareReportsReg is the regular expression matching the lines of
// networksetup command output lines containing the interface information.
var hardwareReportsReg = regexp.MustCompile("Hardware Port: (.*?)\nDevice: (.*?)\n")
// getNetworkSetupHardwareReports parses the output of the `networksetup
// -listallhardwareports` command it returns a map where the key is the
// interface name, and the value is the "hardware port" returns nil if it fails
@@ -52,54 +58,44 @@ func getCurrentHardwarePortInfo(ifaceName string) (hardwarePortInfo, error) {
// TODO(e.burkov): There should be more proper approach than parsing the
// command output. For example, see
// https://developer.apple.com/documentation/systemconfiguration.
func getNetworkSetupHardwareReports() map[string]string {
_, out, err := aghos.RunCommand("networksetup", "-listallhardwareports")
func getNetworkSetupHardwareReports() (reports map[string]string) {
_, out, err := aghosRunCommand("networksetup", "-listallhardwareports")
if err != nil {
return nil
}
re, err := regexp.Compile("Hardware Port: (.*?)\nDevice: (.*?)\n")
if err != nil {
return nil
reports = make(map[string]string)
matches := hardwareReportsReg.FindAllSubmatch(out, -1)
for _, m := range matches {
reports[string(m[2])] = string(m[1])
}
m := make(map[string]string)
matches := re.FindAllStringSubmatch(out, -1)
for i := range matches {
port := matches[i][1]
device := matches[i][2]
m[device] = port
}
return m
return reports
}
func getHardwarePortInfo(hardwarePort string) (hardwarePortInfo, error) {
h := hardwarePortInfo{}
// hardwarePortReg is the regular expression matching the lines of networksetup
// command output lines containing the port information.
var hardwarePortReg = regexp.MustCompile("IP address: (.*?)\nSubnet mask: (.*?)\nRouter: (.*?)\n")
_, out, err := aghos.RunCommand("networksetup", "-getinfo", hardwarePort)
func getHardwarePortInfo(hardwarePort string) (h hardwarePortInfo, err error) {
_, out, err := aghosRunCommand("networksetup", "-getinfo", hardwarePort)
if err != nil {
return h, err
}
re := regexp.MustCompile("IP address: (.*?)\nSubnet mask: (.*?)\nRouter: (.*?)\n")
match := re.FindStringSubmatch(out)
if len(match) == 0 {
match := hardwarePortReg.FindSubmatch(out)
if len(match) != 4 {
return h, errors.Error("could not find hardware port info")
}
h.name = hardwarePort
h.ip = match[1]
h.subnet = match[2]
h.gatewayIP = match[3]
if strings.Index(out, "Manual Configuration") == 0 {
h.static = true
}
return h, nil
return hardwarePortInfo{
name: hardwarePort,
ip: string(match[1]),
subnet: string(match[2]),
gatewayIP: string(match[3]),
static: bytes.Index(out, []byte("Manual Configuration")) == 0,
}, nil
}
func ifaceSetStaticIP(ifaceName string) (err error) {
@@ -109,7 +105,7 @@ func ifaceSetStaticIP(ifaceName string) (err error) {
}
if portInfo.static {
return errors.Error("IP address is already static")
return errors.Error("ip address is already static")
}
dnsAddrs, err := getEtcResolvConfServers()
@@ -117,50 +113,62 @@ func ifaceSetStaticIP(ifaceName string) (err error) {
return err
}
args := make([]string, 0)
args = append(args, "-setdnsservers", portInfo.name)
args = append(args, dnsAddrs...)
args := append([]string{"-setdnsservers", portInfo.name}, dnsAddrs...)
// Setting DNS servers is necessary when configuring a static IP
code, _, err := aghos.RunCommand("networksetup", args...)
code, _, err := aghosRunCommand("networksetup", args...)
if err != nil {
return err
}
if code != 0 {
} else if code != 0 {
return fmt.Errorf("failed to set DNS servers, code=%d", code)
}
// Actually configures hardware port to have static IP
code, _, err = aghos.RunCommand("networksetup", "-setmanual",
portInfo.name, portInfo.ip, portInfo.subnet, portInfo.gatewayIP)
code, _, err = aghosRunCommand(
"networksetup",
"-setmanual",
portInfo.name,
portInfo.ip,
portInfo.subnet,
portInfo.gatewayIP,
)
if err != nil {
return err
}
if code != 0 {
} else if code != 0 {
return fmt.Errorf("failed to set DNS servers, code=%d", code)
}
return nil
}
// etcResolvConfReg is the regular expression matching the lines of resolv.conf
// file containing a name server information.
var etcResolvConfReg = regexp.MustCompile("nameserver ([a-zA-Z0-9.:]+)")
// getEtcResolvConfServers returns a list of nameservers configured in
// /etc/resolv.conf.
func getEtcResolvConfServers() ([]string, error) {
body, err := os.ReadFile("/etc/resolv.conf")
func getEtcResolvConfServers() (addrs []string, err error) {
const filename = "etc/resolv.conf"
_, err = aghos.FileWalker(func(r io.Reader) (_ []string, _ bool, err error) {
sc := bufio.NewScanner(r)
for sc.Scan() {
matches := etcResolvConfReg.FindAllStringSubmatch(sc.Text(), -1)
if len(matches) == 0 {
continue
}
for _, m := range matches {
addrs = append(addrs, m[1])
}
}
return nil, false, sc.Err()
}).Walk(rootDirFS, filename)
if err != nil {
return nil, err
}
re := regexp.MustCompile("nameserver ([a-zA-Z0-9.:]+)")
matches := re.FindAllStringSubmatch(string(body), -1)
if len(matches) == 0 {
return nil, errors.Error("found no DNS servers in /etc/resolv.conf")
}
addrs := make([]string, 0)
for i := range matches {
addrs = append(addrs, matches[i][1])
return nil, fmt.Errorf("parsing etc/resolv.conf file: %w", err)
} else if len(addrs) == 0 {
return nil, fmt.Errorf("found no dns servers in %s", filename)
}
return addrs, nil