all: sync more

This commit is contained in:
Ainar Garipov 2022-06-02 17:55:48 +03:00
parent dcb043df5f
commit 4f5131f423
31 changed files with 1073 additions and 900 deletions
internal/home

View file

@ -4,8 +4,6 @@ import (
"bytes"
"fmt"
"net"
"os/exec"
"runtime"
"sort"
"strings"
"sync"
@ -62,6 +60,16 @@ const (
ClientSourceHostsFile
)
// clientSourceConf is used to configure where the runtime clients will be
// obtained from.
type clientSourcesConf struct {
WHOIS bool `yaml:"whois"`
ARP bool `yaml:"arp"`
RDNS bool `yaml:"rdns"`
DHCP bool `yaml:"dhcp"`
HostsFile bool `yaml:"hosts"`
}
// RuntimeClient information
type RuntimeClient struct {
WHOISInfo *RuntimeClientWHOISInfo
@ -99,6 +107,9 @@ type clientsContainer struct {
// hosts database.
etcHosts *aghnet.HostsContainer
// arpdb stores the neighbors retrieved from ARP.
arpdb aghnet.ARPDB
testing bool // if TRUE, this object is used for internal tests
}
@ -109,6 +120,7 @@ func (clients *clientsContainer) Init(
objects []*clientObject,
dhcpServer *dhcpd.Server,
etcHosts *aghnet.HostsContainer,
arpdb aghnet.ARPDB,
) {
if clients.list != nil {
log.Fatal("clients.list != nil")
@ -121,6 +133,7 @@ func (clients *clientsContainer) Init(
clients.dhcpServer = dhcpServer
clients.etcHosts = etcHosts
clients.arpdb = arpdb
clients.addFromConfig(objects)
if clients.testing {
@ -132,14 +145,14 @@ func (clients *clientsContainer) Init(
clients.dhcpServer.SetOnLeaseChanged(clients.onDHCPLeaseChanged)
}
go clients.handleHostsUpdates()
if clients.etcHosts != nil {
go clients.handleHostsUpdates()
}
}
func (clients *clientsContainer) handleHostsUpdates() {
if clients.etcHosts != nil {
for upd := range clients.etcHosts.Upd() {
clients.addFromHostsFile(upd)
}
for upd := range clients.etcHosts.Upd() {
clients.addFromHostsFile(upd)
}
}
@ -156,7 +169,9 @@ func (clients *clientsContainer) Start() {
// Reload reloads runtime clients.
func (clients *clientsContainer) Reload() {
clients.addFromSystemARP()
if clients.arpdb != nil {
clients.addFromSystemARP()
}
}
type clientObject struct {
@ -255,6 +270,8 @@ func (clients *clientsContainer) forConfig() (objs []*clientObject) {
}
func (clients *clientsContainer) periodicUpdate() {
defer log.OnPanic("clients container")
for {
clients.Reload()
time.Sleep(clientsUpdatePeriod)
@ -733,6 +750,7 @@ func (clients *clientsContainer) addHostLocked(ip net.IP, host string, src clien
return false
}
rc.Host = host
rc.Source = src
} else {
rc = &RuntimeClient{
@ -805,16 +823,18 @@ func (clients *clientsContainer) addFromHostsFile(hosts *netutil.IPMap) {
// addFromSystemARP adds the IP-hostname pairings from the output of the arp -a
// command.
func (clients *clientsContainer) addFromSystemARP() {
if runtime.GOOS == "windows" {
if err := clients.arpdb.Refresh(); err != nil {
log.Error("refreshing arp container: %s", err)
clients.arpdb = aghnet.EmptyARPDB{}
return
}
cmd := exec.Command("arp", "-a")
log.Tracef("executing %q %q", cmd.Path, cmd.Args)
data, err := cmd.Output()
if err != nil || cmd.ProcessState.ExitCode() != 0 {
log.Debug("command %q has failed: %q code:%d",
cmd.Path, err, cmd.ProcessState.ExitCode())
ns := clients.arpdb.Neighbors()
if len(ns) == 0 {
log.Debug("refreshing arp container: the update is empty")
return
}
@ -823,36 +843,20 @@ func (clients *clientsContainer) addFromSystemARP() {
clients.rmHostsBySrc(ClientSourceARP)
n := 0
// TODO(a.garipov): Rewrite to use bufio.Scanner.
lines := strings.Split(string(data), "\n")
for _, ln := range lines {
lparen := strings.Index(ln, " (")
rparen := strings.Index(ln, ") ")
if lparen == -1 || rparen == -1 || lparen >= rparen {
continue
}
host := ln[:lparen]
ipStr := ln[lparen+2 : rparen]
ip := net.ParseIP(ipStr)
if netutil.ValidateDomainName(host) != nil || ip == nil {
continue
}
ok := clients.addHostLocked(ip, host, ClientSourceARP)
if ok {
n++
added := 0
for _, n := range ns {
if clients.addHostLocked(n.IP, n.Name, ClientSourceARP) {
added++
}
}
log.Debug("clients: added %d client aliases from 'arp -a' command output", n)
log.Debug("clients: added %d client aliases from arp neighborhood", added)
}
// updateFromDHCP adds the clients that have a non-empty hostname from the DHCP
// server.
func (clients *clientsContainer) updateFromDHCP(add bool) {
if clients.dhcpServer == nil {
if clients.dhcpServer == nil || !config.Clients.Sources.DHCP {
return
}