mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-08-10 13:20:33 +02:00
cmd/ctrld: ensure cleaning up done when self-uninstall
While at it, also making DNS reset always use DHCP.
This commit is contained in:
+16
-5
@@ -111,11 +111,7 @@ func initCLI() {
|
|||||||
initCache()
|
initCache()
|
||||||
|
|
||||||
if iface == "auto" {
|
if iface == "auto" {
|
||||||
dri, err := interfaces.DefaultRouteInterface()
|
iface = defaultIfaceName()
|
||||||
if err != nil {
|
|
||||||
mainLog.Error().Err(err).Msg("failed to get default route interface")
|
|
||||||
}
|
|
||||||
iface = dri
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if daemon {
|
if daemon {
|
||||||
@@ -450,6 +446,7 @@ func readConfigFile(writeDefaultConfig bool) bool {
|
|||||||
err := v.ReadInConfig()
|
err := v.ReadInConfig()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
fmt.Println("loading config file from:", v.ConfigFileUsed())
|
fmt.Println("loading config file from:", v.ConfigFileUsed())
|
||||||
|
defaultConfigFile = v.ConfigFileUsed()
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,6 +526,12 @@ func processCDFlags() {
|
|||||||
stderrMsg(err.Error())
|
stderrMsg(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if iface == "auto" {
|
||||||
|
iface = defaultIfaceName()
|
||||||
|
}
|
||||||
|
if netIface, _ := netIfaceFromName(iface); netIface != nil {
|
||||||
|
_ = resetDNS(netIface)
|
||||||
|
}
|
||||||
tasks := []task{{s.Uninstall, true}}
|
tasks := []task{{s.Uninstall, true}}
|
||||||
if doTasks(tasks) {
|
if doTasks(tasks) {
|
||||||
log.Println("uninstalled service")
|
log.Println("uninstalled service")
|
||||||
@@ -623,3 +626,11 @@ func netIfaceFromName(ifaceName string) (*net.Interface, error) {
|
|||||||
}
|
}
|
||||||
return iface, err
|
return iface, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func defaultIfaceName() string {
|
||||||
|
dri, err := interfaces.DefaultRouteInterface()
|
||||||
|
if err != nil {
|
||||||
|
mainLog.Error().Err(err).Msg("failed to get default route interface")
|
||||||
|
}
|
||||||
|
return dri
|
||||||
|
}
|
||||||
|
|||||||
+41
-4
@@ -8,6 +8,10 @@ import (
|
|||||||
"os/exec"
|
"os/exec"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||||
|
"github.com/insomniacslk/dhcp/dhcpv4/client4"
|
||||||
|
"github.com/insomniacslk/dhcp/dhcpv6"
|
||||||
|
"github.com/insomniacslk/dhcp/dhcpv6/client6"
|
||||||
"tailscale.com/net/dns"
|
"tailscale.com/net/dns"
|
||||||
"tailscale.com/util/dnsname"
|
"tailscale.com/util/dnsname"
|
||||||
|
|
||||||
@@ -45,7 +49,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
mainLog.Error().Err(err).Msg("failed to create DNS OS configurator")
|
mainLog.Error().Err(err).Msg("failed to create DNS OS configurator")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer r.Close()
|
||||||
ns := make([]netip.Addr, 0, len(nameservers))
|
ns := make([]netip.Addr, 0, len(nameservers))
|
||||||
for _, nameserver := range nameservers {
|
for _, nameserver := range nameservers {
|
||||||
ns = append(ns, netip.MustParseAddr(nameserver))
|
ns = append(ns, netip.MustParseAddr(nameserver))
|
||||||
@@ -56,11 +60,44 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetDNS(iface *net.Interface, nameservers []string) error {
|
func resetDNS(iface *net.Interface) error {
|
||||||
if err := setDNS(iface, nameservers); err != nil {
|
c := client4.NewClient()
|
||||||
mainLog.Error().Err(err).Msg("resetDNS failed.")
|
conversation, err := c.Exchange(iface.Name)
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, packet := range conversation {
|
||||||
|
if packet.MessageType() == dhcpv4.MessageTypeAck {
|
||||||
|
nameservers := packet.DNS()
|
||||||
|
ns := make([]string, 0, len(nameservers))
|
||||||
|
for _, nameserver := range nameservers {
|
||||||
|
ns = append(ns, nameserver.String())
|
||||||
|
}
|
||||||
|
_ = setDNS(iface, ns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if supportsIPv6() {
|
||||||
|
c := client6.NewClient()
|
||||||
|
conversation, err := c.Exchange(iface.Name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
for _, packet := range conversation {
|
||||||
|
if packet.Type() == dhcpv6.MessageTypeReply {
|
||||||
|
msg, err := packet.GetInnerMessage()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
nameservers := msg.Options.DNS()
|
||||||
|
ns := make([]string, 0, len(nameservers))
|
||||||
|
for _, nameserver := range nameservers {
|
||||||
|
ns = append(ns, nameserver.String())
|
||||||
|
}
|
||||||
|
_ = setDNS(iface, ns)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-2
@@ -6,6 +6,8 @@ package main
|
|||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
|
||||||
|
"github.com/Control-D-Inc/ctrld/internal/resolvconffile"
|
||||||
)
|
)
|
||||||
|
|
||||||
// allocate loopback ip
|
// allocate loopback ip
|
||||||
@@ -44,7 +46,7 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cuonglm): use system API
|
// TODO(cuonglm): use system API
|
||||||
func resetDNS(iface *net.Interface, _ []string) error {
|
func resetDNS(iface *net.Interface) error {
|
||||||
cmd := "networksetup"
|
cmd := "networksetup"
|
||||||
args := []string{"-setdnsservers", iface.Name, "empty"}
|
args := []string{"-setdnsservers", iface.Name, "empty"}
|
||||||
|
|
||||||
@@ -56,5 +58,5 @@ func resetDNS(iface *net.Interface, _ []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func currentDNS(_ *net.Interface) []string {
|
func currentDNS(_ *net.Interface) []string {
|
||||||
return nil
|
return resolvconffile.NameServers("")
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-30
@@ -4,7 +4,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@@ -39,14 +38,18 @@ func setDNS(iface *net.Interface, nameservers []string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cuonglm): should we use system API?
|
// TODO(cuonglm): should we use system API?
|
||||||
func resetDNS(iface *net.Interface, nameservers []string) error {
|
func resetDNS(iface *net.Interface) error {
|
||||||
if err := resetDNSUseDHCP(iface); err != nil {
|
if supportsIPv6ListenLocal() {
|
||||||
mainLog.Debug().Err(err).Msg("could not reset DNS using DHCP")
|
if output, err := netsh("interface", "ipv6", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp"); err != nil {
|
||||||
|
mainLog.Warn().Err(err).Msgf("failed to reset ipv6 DNS: %s", string(output))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(nameservers) == 0 {
|
output, err := netsh("interface", "ipv4", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp")
|
||||||
return nil
|
if err != nil {
|
||||||
|
mainLog.Error().Err(err).Msgf("failed to reset ipv4 DNS: %s", string(output))
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
return setDNS(iface, nameservers)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setPrimaryDNS(iface *net.Interface, dns string) error {
|
func setPrimaryDNS(iface *net.Interface, dns string) error {
|
||||||
@@ -80,28 +83,11 @@ func addSecondaryDNS(iface *net.Interface, dns string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func resetDNSUseDHCP(iface *net.Interface) error {
|
|
||||||
if supportsIPv6ListenLocal() {
|
|
||||||
if output, err := netsh("interface", "ipv6", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp"); err != nil {
|
|
||||||
mainLog.Warn().Err(err).Msgf("failed to reset ipv6 DNS: %s", string(output))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
output, err := netsh("interface", "ipv4", "set", "dnsserver", strconv.Itoa(iface.Index), "dhcp")
|
|
||||||
if err != nil {
|
|
||||||
mainLog.Error().Err(err).Msgf("failed to reset ipv4 DNS: %s", string(output))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func netsh(args ...string) ([]byte, error) {
|
func netsh(args ...string) ([]byte, error) {
|
||||||
return exec.Command("netsh", args...).Output()
|
return exec.Command("netsh", args...).Output()
|
||||||
}
|
}
|
||||||
|
|
||||||
func currentDNS(iface *net.Interface) []string {
|
func currentDNS(iface *net.Interface) []string {
|
||||||
if hasDNSFromDHCP(iface, "ipv4") || hasDNSFromDHCP(iface, "ipv6") {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
|
luid, err := winipcfg.LUIDFromIndex(uint32(iface.Index))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Error().Err(err).Msg("failed to get interface LUID")
|
mainLog.Error().Err(err).Msg("failed to get interface LUID")
|
||||||
@@ -118,9 +104,3 @@ func currentDNS(iface *net.Interface) []string {
|
|||||||
}
|
}
|
||||||
return ns
|
return ns
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasDNSFromDHCP(iface *net.Interface, ipVer string) bool {
|
|
||||||
idx := strconv.Itoa(iface.Index)
|
|
||||||
output, _ := netsh("interface", ipVer, "show", "dnsservers", idx)
|
|
||||||
return bytes.Contains(output, []byte(" through DHCP:"))
|
|
||||||
}
|
|
||||||
|
|||||||
+3
-5
@@ -23,9 +23,8 @@ var svcConfig = &service.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
type prog struct {
|
type prog struct {
|
||||||
cfg *ctrld.Config
|
cfg *ctrld.Config
|
||||||
cache dnscache.Cacher
|
cache dnscache.Cacher
|
||||||
origDNS []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *prog) Start(s service.Service) error {
|
func (p *prog) Start(s service.Service) error {
|
||||||
@@ -40,7 +39,6 @@ func (p *prog) run() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
mainLog.Error().Err(err).Msg("could not get interface")
|
mainLog.Error().Err(err).Msg("could not get interface")
|
||||||
} else {
|
} else {
|
||||||
p.origDNS = currentDNS(netIface)
|
|
||||||
if err := setDNS(netIface, []string{cfg.Listener["0"].IP}); err != nil {
|
if err := setDNS(netIface, []string{cfg.Listener["0"].IP}); err != nil {
|
||||||
mainLog.Error().Err(err).Str("iface", iface).Msgf("could not set DNS for interface")
|
mainLog.Error().Err(err).Str("iface", iface).Msgf("could not set DNS for interface")
|
||||||
}
|
}
|
||||||
@@ -179,7 +177,7 @@ func (p *prog) Stop(s service.Service) error {
|
|||||||
}
|
}
|
||||||
if iface != "" {
|
if iface != "" {
|
||||||
if netIface, err := netIfaceFromName(iface); err == nil {
|
if netIface, err := netIfaceFromName(iface); err == nil {
|
||||||
if err := resetDNS(netIface, p.origDNS); err != nil {
|
if err := resetDNS(netIface); err != nil {
|
||||||
mainLog.Error().Err(err).Str("iface", iface).Msgf("could not reset DNS")
|
mainLog.Error().Err(err).Str("iface", iface).Msgf("could not reset DNS")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user