safing-portmaster/netenv/environment_windows.go
2020-07-15 08:53:55 +02:00

95 lines
2.1 KiB
Go

package netenv
import (
"bufio"
"bytes"
"context"
"net"
"os/exec"
"strings"
"sync"
"time"
"github.com/safing/portbase/log"
)
const (
nameserversRecheck = 2 * time.Second
)
var (
nameservers = make([]Nameserver, 0)
nameserversLock sync.Mutex
nameserversExpires = time.Now()
)
// Nameservers returns the currently active nameservers.
func Nameservers() []Nameserver {
// locking
nameserversLock.Lock()
defer nameserversLock.Unlock()
// cache
if nameserversExpires.After(time.Now()) {
return nameservers
}
// update cache expiry when finished
defer func() {
nameserversExpires = time.Now().Add(nameserversRecheck)
}()
// reset
nameservers = make([]Nameserver, 0)
// This is a preliminary workaround until we have more time for proper interface using iphlpapi.dll
// TODO: make nice implementation
var output = make(chan []byte, 1)
module.StartWorker("get assigned nameservers", func(ctx context.Context) error {
cmd := exec.CommandContext(ctx, "nslookup", "localhost")
data, err := cmd.CombinedOutput()
if err != nil {
log.Debugf("netenv: failed to get assigned nameserves: %s", err)
output <- nil
} else {
output <- data
}
return nil
})
select {
case data := <-output:
scanner := bufio.NewScanner(bytes.NewReader(data))
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
// check if we found the correct line
if !strings.HasPrefix(scanner.Text(), "Address:") {
continue
}
// split into fields, check if we have enough fields
fields := strings.Fields(scanner.Text())
if len(fields) < 2 {
continue
}
// parse nameserver, return if valid IP found
ns := net.ParseIP(fields[1])
if ns != nil {
nameservers = append(nameservers, Nameserver{
IP: ns,
})
return nameservers
}
}
log.Debug("netenv: could not find assigned nameserver")
return nameservers
case <-time.After(5 * time.Second):
log.Debug("netenv: timed out while getting assigned nameserves")
}
return nameservers
}
// Gateways returns the currently active gateways.
func Gateways() []net.IP {
return nil
}