mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2024-11-21 20:45:33 +03:00
Pull request 1989: AG-24794-client-source
Squashed commit of the following: commit 5cf83aafc8ddfea15b4f8e9b4061af021727f68c Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Fri Sep 1 14:58:03 2023 +0300 client: imp code commit 4325c8f610d1329ad38c800e20275668f1690f51 Author: Stanislav Chzhen <s.chzhen@adguard.com> Date: Fri Sep 1 14:38:33 2023 +0300 all: add client source
This commit is contained in:
parent
0182b9ec18
commit
905f9615a8
6 changed files with 93 additions and 86 deletions
|
@ -77,8 +77,8 @@ func (n Neighbor) Clone() (clone Neighbor) {
|
|||
}
|
||||
}
|
||||
|
||||
// validatedHostname returns valid hostname. Otherwise returns empty string and
|
||||
// logs the error if hostname is not valid.
|
||||
// validatedHostname returns h if it's a valid hostname, or an empty string
|
||||
// otherwise, logging the validation error.
|
||||
func validatedHostname(h string) (host string) {
|
||||
err := netutil.ValidateHostname(h)
|
||||
if err != nil {
|
||||
|
|
|
@ -3,3 +3,52 @@
|
|||
//
|
||||
// TODO(a.garipov): Expand.
|
||||
package client
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Source represents the source from which the information about the client has
|
||||
// been obtained.
|
||||
type Source uint8
|
||||
|
||||
// Clients information sources. The order determines the priority.
|
||||
const (
|
||||
SourceNone Source = iota
|
||||
SourceWHOIS
|
||||
SourceARP
|
||||
SourceRDNS
|
||||
SourceDHCP
|
||||
SourceHostsFile
|
||||
SourcePersistent
|
||||
)
|
||||
|
||||
// type check
|
||||
var _ fmt.Stringer = Source(0)
|
||||
|
||||
// String returns a human-readable name of cs.
|
||||
func (cs Source) String() (s string) {
|
||||
switch cs {
|
||||
case SourceWHOIS:
|
||||
return "WHOIS"
|
||||
case SourceARP:
|
||||
return "ARP"
|
||||
case SourceRDNS:
|
||||
return "rDNS"
|
||||
case SourceDHCP:
|
||||
return "DHCP"
|
||||
case SourceHostsFile:
|
||||
return "etc/hosts"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ encoding.TextMarshaler = Source(0)
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler for the Source.
|
||||
func (cs Source) MarshalText() (text []byte, err error) {
|
||||
return []byte(cs.String()), nil
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package home
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||
|
@ -83,50 +83,6 @@ func (c *Client) setSafeSearch(
|
|||
return nil
|
||||
}
|
||||
|
||||
// clientSource represents the source from which the information about the
|
||||
// client has been obtained.
|
||||
type clientSource uint
|
||||
|
||||
// Clients information sources. The order determines the priority.
|
||||
const (
|
||||
ClientSourceNone clientSource = iota
|
||||
ClientSourceWHOIS
|
||||
ClientSourceARP
|
||||
ClientSourceRDNS
|
||||
ClientSourceDHCP
|
||||
ClientSourceHostsFile
|
||||
ClientSourcePersistent
|
||||
)
|
||||
|
||||
// type check
|
||||
var _ fmt.Stringer = clientSource(0)
|
||||
|
||||
// String returns a human-readable name of cs.
|
||||
func (cs clientSource) String() (s string) {
|
||||
switch cs {
|
||||
case ClientSourceWHOIS:
|
||||
return "WHOIS"
|
||||
case ClientSourceARP:
|
||||
return "ARP"
|
||||
case ClientSourceRDNS:
|
||||
return "rDNS"
|
||||
case ClientSourceDHCP:
|
||||
return "DHCP"
|
||||
case ClientSourceHostsFile:
|
||||
return "etc/hosts"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// type check
|
||||
var _ encoding.TextMarshaler = clientSource(0)
|
||||
|
||||
// MarshalText implements encoding.TextMarshaler for the clientSource.
|
||||
func (cs clientSource) MarshalText() (text []byte, err error) {
|
||||
return []byte(cs.String()), nil
|
||||
}
|
||||
|
||||
// RuntimeClient is a client information about which has been obtained using the
|
||||
// source described in the Source field.
|
||||
type RuntimeClient struct {
|
||||
|
@ -138,5 +94,5 @@ type RuntimeClient struct {
|
|||
|
||||
// Source is the source from which the information about the client has
|
||||
// been obtained.
|
||||
Source clientSource
|
||||
Source client.Source
|
||||
}
|
||||
|
|
|
@ -307,15 +307,15 @@ func (clients *clientsContainer) periodicUpdate() {
|
|||
}
|
||||
|
||||
// clientSource checks if client with this IP address already exists and returns
|
||||
// the source which updated it last. It returns [ClientSourceNone] if the
|
||||
// the source which updated it last. It returns [client.SourceNone] if the
|
||||
// client doesn't exist.
|
||||
func (clients *clientsContainer) clientSource(ip netip.Addr) (src clientSource) {
|
||||
func (clients *clientsContainer) clientSource(ip netip.Addr) (src client.Source) {
|
||||
clients.lock.Lock()
|
||||
defer clients.lock.Unlock()
|
||||
|
||||
_, ok := clients.findLocked(ip.String())
|
||||
if ok {
|
||||
return ClientSourcePersistent
|
||||
return client.SourcePersistent
|
||||
}
|
||||
|
||||
rc, ok := clients.ipToRC[ip]
|
||||
|
@ -323,8 +323,8 @@ func (clients *clientsContainer) clientSource(ip netip.Addr) (src clientSource)
|
|||
src = rc.Source
|
||||
}
|
||||
|
||||
if src < ClientSourceDHCP && clients.dhcp.HostByIP(ip) != "" {
|
||||
src = ClientSourceDHCP
|
||||
if src < client.SourceDHCP && clients.dhcp.HostByIP(ip) != "" {
|
||||
src = client.SourceDHCP
|
||||
}
|
||||
|
||||
return src
|
||||
|
@ -533,7 +533,7 @@ func (clients *clientsContainer) runtimeClient(ip netip.Addr) (rc *RuntimeClient
|
|||
|
||||
// findRuntimeClient finds a runtime client by their IP.
|
||||
func (clients *clientsContainer) findRuntimeClient(ip netip.Addr) (rc *RuntimeClient, ok bool) {
|
||||
if rc, ok = clients.runtimeClient(ip); ok && rc.Source > ClientSourceDHCP {
|
||||
if rc, ok = clients.runtimeClient(ip); ok && rc.Source > client.SourceDHCP {
|
||||
return rc, ok
|
||||
}
|
||||
|
||||
|
@ -544,7 +544,7 @@ func (clients *clientsContainer) findRuntimeClient(ip netip.Addr) (rc *RuntimeCl
|
|||
|
||||
return &RuntimeClient{
|
||||
Host: host,
|
||||
Source: ClientSourceDHCP,
|
||||
Source: client.SourceDHCP,
|
||||
WHOIS: &whois.Info{},
|
||||
}, true
|
||||
}
|
||||
|
@ -744,7 +744,7 @@ func (clients *clientsContainer) setWHOISInfo(ip netip.Addr, wi *whois.Info) {
|
|||
// Create a RuntimeClient implicitly so that we don't do this check
|
||||
// again.
|
||||
rc = &RuntimeClient{
|
||||
Source: ClientSourceWHOIS,
|
||||
Source: client.SourceWHOIS,
|
||||
}
|
||||
clients.ipToRC[ip] = rc
|
||||
|
||||
|
@ -763,7 +763,7 @@ func (clients *clientsContainer) setWHOISInfo(ip netip.Addr, wi *whois.Info) {
|
|||
func (clients *clientsContainer) addHost(
|
||||
ip netip.Addr,
|
||||
host string,
|
||||
src clientSource,
|
||||
src client.Source,
|
||||
) (ok bool) {
|
||||
clients.lock.Lock()
|
||||
defer clients.lock.Unlock()
|
||||
|
@ -786,7 +786,7 @@ func (clients *clientsContainer) UpdateAddress(ip netip.Addr, host string, info
|
|||
defer clients.lock.Unlock()
|
||||
|
||||
if host != "" {
|
||||
ok := clients.addHostLocked(ip, host, ClientSourceRDNS)
|
||||
ok := clients.addHostLocked(ip, host, client.SourceRDNS)
|
||||
if !ok {
|
||||
log.Debug("clients: host for client %q already set with higher priority source", ip)
|
||||
}
|
||||
|
@ -802,11 +802,11 @@ func (clients *clientsContainer) UpdateAddress(ip netip.Addr, host string, info
|
|||
func (clients *clientsContainer) addHostLocked(
|
||||
ip netip.Addr,
|
||||
host string,
|
||||
src clientSource,
|
||||
src client.Source,
|
||||
) (ok bool) {
|
||||
rc, ok := clients.ipToRC[ip]
|
||||
if !ok {
|
||||
if src < ClientSourceDHCP {
|
||||
if src < client.SourceDHCP {
|
||||
if clients.dhcp.HostByIP(ip) != "" {
|
||||
return false
|
||||
}
|
||||
|
@ -829,7 +829,7 @@ func (clients *clientsContainer) addHostLocked(
|
|||
}
|
||||
|
||||
// rmHostsBySrc removes all entries that match the specified source.
|
||||
func (clients *clientsContainer) rmHostsBySrc(src clientSource) {
|
||||
func (clients *clientsContainer) rmHostsBySrc(src client.Source) {
|
||||
n := 0
|
||||
for ip, rc := range clients.ipToRC {
|
||||
if rc.Source == src {
|
||||
|
@ -847,7 +847,7 @@ func (clients *clientsContainer) addFromHostsFile(hosts aghnet.Hosts) {
|
|||
clients.lock.Lock()
|
||||
defer clients.lock.Unlock()
|
||||
|
||||
clients.rmHostsBySrc(ClientSourceHostsFile)
|
||||
clients.rmHostsBySrc(client.SourceHostsFile)
|
||||
|
||||
n := 0
|
||||
for addr, rec := range hosts {
|
||||
|
@ -855,7 +855,7 @@ func (clients *clientsContainer) addFromHostsFile(hosts aghnet.Hosts) {
|
|||
// hostname for the IP address.
|
||||
//
|
||||
// TODO(e.burkov): Consider using all the names from all the records.
|
||||
clients.addHostLocked(addr, rec[0].Names[0], ClientSourceHostsFile)
|
||||
clients.addHostLocked(addr, rec[0].Names[0], client.SourceHostsFile)
|
||||
n++
|
||||
}
|
||||
|
||||
|
@ -883,11 +883,11 @@ func (clients *clientsContainer) addFromSystemARP() {
|
|||
clients.lock.Lock()
|
||||
defer clients.lock.Unlock()
|
||||
|
||||
clients.rmHostsBySrc(ClientSourceARP)
|
||||
clients.rmHostsBySrc(client.SourceARP)
|
||||
|
||||
added := 0
|
||||
for _, n := range ns {
|
||||
if clients.addHostLocked(n.IP, n.Name, ClientSourceARP) {
|
||||
if clients.addHostLocked(n.IP, n.Name, client.SourceARP) {
|
||||
added++
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
|
@ -99,9 +100,9 @@ func TestClients(t *testing.T) {
|
|||
|
||||
assert.Equal(t, "client2", c.Name)
|
||||
|
||||
assert.Equal(t, clients.clientSource(cliNoneIP), ClientSourceNone)
|
||||
assert.Equal(t, clients.clientSource(cli1IP), ClientSourcePersistent)
|
||||
assert.Equal(t, clients.clientSource(cli2IP), ClientSourcePersistent)
|
||||
assert.Equal(t, clients.clientSource(cliNoneIP), client.SourceNone)
|
||||
assert.Equal(t, clients.clientSource(cli1IP), client.SourcePersistent)
|
||||
assert.Equal(t, clients.clientSource(cli2IP), client.SourcePersistent)
|
||||
})
|
||||
|
||||
t.Run("add_fail_name", func(t *testing.T) {
|
||||
|
@ -148,8 +149,8 @@ func TestClients(t *testing.T) {
|
|||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, clients.clientSource(cliOldIP), ClientSourceNone)
|
||||
assert.Equal(t, clients.clientSource(cliNewIP), ClientSourcePersistent)
|
||||
assert.Equal(t, clients.clientSource(cliOldIP), client.SourceNone)
|
||||
assert.Equal(t, clients.clientSource(cliNewIP), client.SourcePersistent)
|
||||
|
||||
prev, ok = clients.list["client1"]
|
||||
require.True(t, ok)
|
||||
|
@ -181,7 +182,7 @@ func TestClients(t *testing.T) {
|
|||
ok := clients.Del("client1-renamed")
|
||||
require.True(t, ok)
|
||||
|
||||
assert.Equal(t, clients.clientSource(netip.MustParseAddr("1.1.1.2")), ClientSourceNone)
|
||||
assert.Equal(t, clients.clientSource(netip.MustParseAddr("1.1.1.2")), client.SourceNone)
|
||||
})
|
||||
|
||||
t.Run("del_fail", func(t *testing.T) {
|
||||
|
@ -191,32 +192,32 @@ func TestClients(t *testing.T) {
|
|||
|
||||
t.Run("addhost_success", func(t *testing.T) {
|
||||
ip := netip.MustParseAddr("1.1.1.1")
|
||||
ok := clients.addHost(ip, "host", ClientSourceARP)
|
||||
ok := clients.addHost(ip, "host", client.SourceARP)
|
||||
assert.True(t, ok)
|
||||
|
||||
ok = clients.addHost(ip, "host2", ClientSourceARP)
|
||||
ok = clients.addHost(ip, "host2", client.SourceARP)
|
||||
assert.True(t, ok)
|
||||
|
||||
ok = clients.addHost(ip, "host3", ClientSourceHostsFile)
|
||||
ok = clients.addHost(ip, "host3", client.SourceHostsFile)
|
||||
assert.True(t, ok)
|
||||
|
||||
assert.Equal(t, clients.clientSource(ip), ClientSourceHostsFile)
|
||||
assert.Equal(t, clients.clientSource(ip), client.SourceHostsFile)
|
||||
})
|
||||
|
||||
t.Run("dhcp_replaces_arp", func(t *testing.T) {
|
||||
ip := netip.MustParseAddr("1.2.3.4")
|
||||
ok := clients.addHost(ip, "from_arp", ClientSourceARP)
|
||||
ok := clients.addHost(ip, "from_arp", client.SourceARP)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, clients.clientSource(ip), ClientSourceARP)
|
||||
assert.Equal(t, clients.clientSource(ip), client.SourceARP)
|
||||
|
||||
ok = clients.addHost(ip, "from_dhcp", ClientSourceDHCP)
|
||||
ok = clients.addHost(ip, "from_dhcp", client.SourceDHCP)
|
||||
assert.True(t, ok)
|
||||
assert.Equal(t, clients.clientSource(ip), ClientSourceDHCP)
|
||||
assert.Equal(t, clients.clientSource(ip), client.SourceDHCP)
|
||||
})
|
||||
|
||||
t.Run("addhost_fail", func(t *testing.T) {
|
||||
ip := netip.MustParseAddr("1.1.1.1")
|
||||
ok := clients.addHost(ip, "host1", ClientSourceRDNS)
|
||||
ok := clients.addHost(ip, "host1", client.SourceRDNS)
|
||||
assert.False(t, ok)
|
||||
})
|
||||
}
|
||||
|
@ -239,7 +240,7 @@ func TestClientsWHOIS(t *testing.T) {
|
|||
|
||||
t.Run("existing_auto-client", func(t *testing.T) {
|
||||
ip := netip.MustParseAddr("1.1.1.1")
|
||||
ok := clients.addHost(ip, "host", ClientSourceRDNS)
|
||||
ok := clients.addHost(ip, "host", client.SourceRDNS)
|
||||
assert.True(t, ok)
|
||||
|
||||
clients.setWHOISInfo(ip, whois)
|
||||
|
@ -282,7 +283,7 @@ func TestClientsAddExisting(t *testing.T) {
|
|||
assert.True(t, ok)
|
||||
|
||||
// Now add an auto-client with the same IP.
|
||||
ok = clients.addHost(ip, "test", ClientSourceRDNS)
|
||||
ok = clients.addHost(ip, "test", client.SourceRDNS)
|
||||
assert.True(t, ok)
|
||||
})
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/schedule"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||
|
@ -88,9 +89,9 @@ func (j *clientJSON) copySettings(
|
|||
type runtimeClientJSON struct {
|
||||
WHOIS *whois.Info `json:"whois_info"`
|
||||
|
||||
IP netip.Addr `json:"ip"`
|
||||
Name string `json:"name"`
|
||||
Source clientSource `json:"source"`
|
||||
IP netip.Addr `json:"ip"`
|
||||
Name string `json:"name"`
|
||||
Source client.Source `json:"source"`
|
||||
}
|
||||
|
||||
type clientListJSON struct {
|
||||
|
@ -126,7 +127,7 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
|||
for _, l := range clients.dhcp.Leases() {
|
||||
cj := runtimeClientJSON{
|
||||
Name: l.Hostname,
|
||||
Source: ClientSourceDHCP,
|
||||
Source: client.SourceDHCP,
|
||||
IP: l.IP,
|
||||
WHOIS: &whois.Info{},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue