mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
115 lines
3.2 KiB
Go
115 lines
3.2 KiB
Go
package cli
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"fmt"
|
|
"net"
|
|
"os/exec"
|
|
"strings"
|
|
|
|
"github.com/Control-D-Inc/ctrld/internal/resolvconffile"
|
|
)
|
|
|
|
// allocate loopback ip
|
|
// sudo ifconfig lo0 alias 127.0.0.2 up
|
|
func allocateIP(ip string) error {
|
|
cmd := exec.Command("ifconfig", "lo0", "alias", ip, "up")
|
|
if err := cmd.Run(); err != nil {
|
|
mainLog.Load().Error().Err(err).Msg("allocateIP failed")
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func deAllocateIP(ip string) error {
|
|
cmd := exec.Command("ifconfig", "lo0", "-alias", ip)
|
|
if err := cmd.Run(); err != nil {
|
|
mainLog.Load().Error().Err(err).Msg("deAllocateIP failed")
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// setDnsIgnoreUnusableInterface likes setDNS, but return a nil error if the interface is not usable.
|
|
func setDnsIgnoreUnusableInterface(iface *net.Interface, nameservers []string) error {
|
|
if err := setDNS(iface, nameservers); err != nil {
|
|
// TODO: investiate whether we can detect this without relying on error message.
|
|
if strings.Contains(err.Error(), " is not a recognized network service") {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// set the dns server for the provided network interface
|
|
// networksetup -setdnsservers Wi-Fi 8.8.8.8 1.1.1.1
|
|
// TODO(cuonglm): use system API
|
|
func setDNS(iface *net.Interface, nameservers []string) error {
|
|
// Note that networksetup won't modify search domains settings,
|
|
// This assignment is just a placeholder to silent linter.
|
|
_ = searchDomains
|
|
cmd := "networksetup"
|
|
args := []string{"-setdnsservers", iface.Name}
|
|
args = append(args, nameservers...)
|
|
if out, err := exec.Command(cmd, args...).CombinedOutput(); err != nil {
|
|
return fmt.Errorf("%v: %w", string(out), err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// resetDnsIgnoreUnusableInterface likes resetDNS, but return a nil error if the interface is not usable.
|
|
func resetDnsIgnoreUnusableInterface(iface *net.Interface) error {
|
|
if err := resetDNS(iface); err != nil {
|
|
// TODO: investiate whether we can detect this without relying on error message.
|
|
if strings.Contains(err.Error(), " is not a recognized network service") {
|
|
return nil
|
|
}
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// TODO(cuonglm): use system API
|
|
func resetDNS(iface *net.Interface) error {
|
|
cmd := "networksetup"
|
|
args := []string{"-setdnsservers", iface.Name, "empty"}
|
|
if out, err := exec.Command(cmd, args...).CombinedOutput(); err != nil {
|
|
return fmt.Errorf("%v: %w", string(out), err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// restoreDNS restores the DNS settings of the given interface.
|
|
// this should only be executed upon turning off the ctrld service.
|
|
func restoreDNS(iface *net.Interface) (err error) {
|
|
if ns := savedStaticNameservers(iface); len(ns) > 0 {
|
|
err = setDNS(iface, ns)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func currentDNS(_ *net.Interface) []string {
|
|
return resolvconffile.NameServers()
|
|
}
|
|
|
|
// currentStaticDNS returns the current static DNS settings of given interface.
|
|
func currentStaticDNS(iface *net.Interface) ([]string, error) {
|
|
cmd := "networksetup"
|
|
args := []string{"-getdnsservers", iface.Name}
|
|
out, err := exec.Command(cmd, args...).Output()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
scanner := bufio.NewScanner(bytes.NewReader(out))
|
|
var ns []string
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
if ip := net.ParseIP(line); ip != nil {
|
|
ns = append(ns, ip.String())
|
|
}
|
|
}
|
|
return ns, nil
|
|
}
|