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
|
@ -77,8 +77,8 @@ func (n Neighbor) Clone() (clone Neighbor) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// validatedHostname returns valid hostname. Otherwise returns empty string and
|
// validatedHostname returns h if it's a valid hostname, or an empty string
|
||||||
// logs the error if hostname is not valid.
|
// otherwise, logging the validation error.
|
||||||
func validatedHostname(h string) (host string) {
|
func validatedHostname(h string) (host string) {
|
||||||
err := netutil.ValidateHostname(h)
|
err := netutil.ValidateHostname(h)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -3,3 +3,52 @@
|
||||||
//
|
//
|
||||||
// TODO(a.garipov): Expand.
|
// TODO(a.garipov): Expand.
|
||||||
package client
|
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
|
package home
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering/safesearch"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||||
|
@ -83,50 +83,6 @@ func (c *Client) setSafeSearch(
|
||||||
return nil
|
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
|
// RuntimeClient is a client information about which has been obtained using the
|
||||||
// source described in the Source field.
|
// source described in the Source field.
|
||||||
type RuntimeClient struct {
|
type RuntimeClient struct {
|
||||||
|
@ -138,5 +94,5 @@ type RuntimeClient struct {
|
||||||
|
|
||||||
// Source is the source from which the information about the client has
|
// Source is the source from which the information about the client has
|
||||||
// been obtained.
|
// 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
|
// 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.
|
// 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()
|
clients.lock.Lock()
|
||||||
defer clients.lock.Unlock()
|
defer clients.lock.Unlock()
|
||||||
|
|
||||||
_, ok := clients.findLocked(ip.String())
|
_, ok := clients.findLocked(ip.String())
|
||||||
if ok {
|
if ok {
|
||||||
return ClientSourcePersistent
|
return client.SourcePersistent
|
||||||
}
|
}
|
||||||
|
|
||||||
rc, ok := clients.ipToRC[ip]
|
rc, ok := clients.ipToRC[ip]
|
||||||
|
@ -323,8 +323,8 @@ func (clients *clientsContainer) clientSource(ip netip.Addr) (src clientSource)
|
||||||
src = rc.Source
|
src = rc.Source
|
||||||
}
|
}
|
||||||
|
|
||||||
if src < ClientSourceDHCP && clients.dhcp.HostByIP(ip) != "" {
|
if src < client.SourceDHCP && clients.dhcp.HostByIP(ip) != "" {
|
||||||
src = ClientSourceDHCP
|
src = client.SourceDHCP
|
||||||
}
|
}
|
||||||
|
|
||||||
return src
|
return src
|
||||||
|
@ -533,7 +533,7 @@ func (clients *clientsContainer) runtimeClient(ip netip.Addr) (rc *RuntimeClient
|
||||||
|
|
||||||
// findRuntimeClient finds a runtime client by their IP.
|
// findRuntimeClient finds a runtime client by their IP.
|
||||||
func (clients *clientsContainer) findRuntimeClient(ip netip.Addr) (rc *RuntimeClient, ok bool) {
|
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
|
return rc, ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -544,7 +544,7 @@ func (clients *clientsContainer) findRuntimeClient(ip netip.Addr) (rc *RuntimeCl
|
||||||
|
|
||||||
return &RuntimeClient{
|
return &RuntimeClient{
|
||||||
Host: host,
|
Host: host,
|
||||||
Source: ClientSourceDHCP,
|
Source: client.SourceDHCP,
|
||||||
WHOIS: &whois.Info{},
|
WHOIS: &whois.Info{},
|
||||||
}, true
|
}, 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
|
// Create a RuntimeClient implicitly so that we don't do this check
|
||||||
// again.
|
// again.
|
||||||
rc = &RuntimeClient{
|
rc = &RuntimeClient{
|
||||||
Source: ClientSourceWHOIS,
|
Source: client.SourceWHOIS,
|
||||||
}
|
}
|
||||||
clients.ipToRC[ip] = rc
|
clients.ipToRC[ip] = rc
|
||||||
|
|
||||||
|
@ -763,7 +763,7 @@ func (clients *clientsContainer) setWHOISInfo(ip netip.Addr, wi *whois.Info) {
|
||||||
func (clients *clientsContainer) addHost(
|
func (clients *clientsContainer) addHost(
|
||||||
ip netip.Addr,
|
ip netip.Addr,
|
||||||
host string,
|
host string,
|
||||||
src clientSource,
|
src client.Source,
|
||||||
) (ok bool) {
|
) (ok bool) {
|
||||||
clients.lock.Lock()
|
clients.lock.Lock()
|
||||||
defer clients.lock.Unlock()
|
defer clients.lock.Unlock()
|
||||||
|
@ -786,7 +786,7 @@ func (clients *clientsContainer) UpdateAddress(ip netip.Addr, host string, info
|
||||||
defer clients.lock.Unlock()
|
defer clients.lock.Unlock()
|
||||||
|
|
||||||
if host != "" {
|
if host != "" {
|
||||||
ok := clients.addHostLocked(ip, host, ClientSourceRDNS)
|
ok := clients.addHostLocked(ip, host, client.SourceRDNS)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Debug("clients: host for client %q already set with higher priority source", ip)
|
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(
|
func (clients *clientsContainer) addHostLocked(
|
||||||
ip netip.Addr,
|
ip netip.Addr,
|
||||||
host string,
|
host string,
|
||||||
src clientSource,
|
src client.Source,
|
||||||
) (ok bool) {
|
) (ok bool) {
|
||||||
rc, ok := clients.ipToRC[ip]
|
rc, ok := clients.ipToRC[ip]
|
||||||
if !ok {
|
if !ok {
|
||||||
if src < ClientSourceDHCP {
|
if src < client.SourceDHCP {
|
||||||
if clients.dhcp.HostByIP(ip) != "" {
|
if clients.dhcp.HostByIP(ip) != "" {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -829,7 +829,7 @@ func (clients *clientsContainer) addHostLocked(
|
||||||
}
|
}
|
||||||
|
|
||||||
// rmHostsBySrc removes all entries that match the specified source.
|
// rmHostsBySrc removes all entries that match the specified source.
|
||||||
func (clients *clientsContainer) rmHostsBySrc(src clientSource) {
|
func (clients *clientsContainer) rmHostsBySrc(src client.Source) {
|
||||||
n := 0
|
n := 0
|
||||||
for ip, rc := range clients.ipToRC {
|
for ip, rc := range clients.ipToRC {
|
||||||
if rc.Source == src {
|
if rc.Source == src {
|
||||||
|
@ -847,7 +847,7 @@ func (clients *clientsContainer) addFromHostsFile(hosts aghnet.Hosts) {
|
||||||
clients.lock.Lock()
|
clients.lock.Lock()
|
||||||
defer clients.lock.Unlock()
|
defer clients.lock.Unlock()
|
||||||
|
|
||||||
clients.rmHostsBySrc(ClientSourceHostsFile)
|
clients.rmHostsBySrc(client.SourceHostsFile)
|
||||||
|
|
||||||
n := 0
|
n := 0
|
||||||
for addr, rec := range hosts {
|
for addr, rec := range hosts {
|
||||||
|
@ -855,7 +855,7 @@ func (clients *clientsContainer) addFromHostsFile(hosts aghnet.Hosts) {
|
||||||
// hostname for the IP address.
|
// hostname for the IP address.
|
||||||
//
|
//
|
||||||
// TODO(e.burkov): Consider using all the names from all the records.
|
// 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++
|
n++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -883,11 +883,11 @@ func (clients *clientsContainer) addFromSystemARP() {
|
||||||
clients.lock.Lock()
|
clients.lock.Lock()
|
||||||
defer clients.lock.Unlock()
|
defer clients.lock.Unlock()
|
||||||
|
|
||||||
clients.rmHostsBySrc(ClientSourceARP)
|
clients.rmHostsBySrc(client.SourceARP)
|
||||||
|
|
||||||
added := 0
|
added := 0
|
||||||
for _, n := range ns {
|
for _, n := range ns {
|
||||||
if clients.addHostLocked(n.IP, n.Name, ClientSourceARP) {
|
if clients.addHostLocked(n.IP, n.Name, client.SourceARP) {
|
||||||
added++
|
added++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
"github.com/AdguardTeam/AdGuardHome/internal/dhcpd"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
"github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||||
|
@ -99,9 +100,9 @@ func TestClients(t *testing.T) {
|
||||||
|
|
||||||
assert.Equal(t, "client2", c.Name)
|
assert.Equal(t, "client2", c.Name)
|
||||||
|
|
||||||
assert.Equal(t, clients.clientSource(cliNoneIP), ClientSourceNone)
|
assert.Equal(t, clients.clientSource(cliNoneIP), client.SourceNone)
|
||||||
assert.Equal(t, clients.clientSource(cli1IP), ClientSourcePersistent)
|
assert.Equal(t, clients.clientSource(cli1IP), client.SourcePersistent)
|
||||||
assert.Equal(t, clients.clientSource(cli2IP), ClientSourcePersistent)
|
assert.Equal(t, clients.clientSource(cli2IP), client.SourcePersistent)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("add_fail_name", func(t *testing.T) {
|
t.Run("add_fail_name", func(t *testing.T) {
|
||||||
|
@ -148,8 +149,8 @@ func TestClients(t *testing.T) {
|
||||||
})
|
})
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, clients.clientSource(cliOldIP), ClientSourceNone)
|
assert.Equal(t, clients.clientSource(cliOldIP), client.SourceNone)
|
||||||
assert.Equal(t, clients.clientSource(cliNewIP), ClientSourcePersistent)
|
assert.Equal(t, clients.clientSource(cliNewIP), client.SourcePersistent)
|
||||||
|
|
||||||
prev, ok = clients.list["client1"]
|
prev, ok = clients.list["client1"]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
|
@ -181,7 +182,7 @@ func TestClients(t *testing.T) {
|
||||||
ok := clients.Del("client1-renamed")
|
ok := clients.Del("client1-renamed")
|
||||||
require.True(t, ok)
|
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) {
|
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) {
|
t.Run("addhost_success", func(t *testing.T) {
|
||||||
ip := netip.MustParseAddr("1.1.1.1")
|
ip := netip.MustParseAddr("1.1.1.1")
|
||||||
ok := clients.addHost(ip, "host", ClientSourceARP)
|
ok := clients.addHost(ip, "host", client.SourceARP)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
ok = clients.addHost(ip, "host2", ClientSourceARP)
|
ok = clients.addHost(ip, "host2", client.SourceARP)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
ok = clients.addHost(ip, "host3", ClientSourceHostsFile)
|
ok = clients.addHost(ip, "host3", client.SourceHostsFile)
|
||||||
assert.True(t, ok)
|
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) {
|
t.Run("dhcp_replaces_arp", func(t *testing.T) {
|
||||||
ip := netip.MustParseAddr("1.2.3.4")
|
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.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.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) {
|
t.Run("addhost_fail", func(t *testing.T) {
|
||||||
ip := netip.MustParseAddr("1.1.1.1")
|
ip := netip.MustParseAddr("1.1.1.1")
|
||||||
ok := clients.addHost(ip, "host1", ClientSourceRDNS)
|
ok := clients.addHost(ip, "host1", client.SourceRDNS)
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -239,7 +240,7 @@ func TestClientsWHOIS(t *testing.T) {
|
||||||
|
|
||||||
t.Run("existing_auto-client", func(t *testing.T) {
|
t.Run("existing_auto-client", func(t *testing.T) {
|
||||||
ip := netip.MustParseAddr("1.1.1.1")
|
ip := netip.MustParseAddr("1.1.1.1")
|
||||||
ok := clients.addHost(ip, "host", ClientSourceRDNS)
|
ok := clients.addHost(ip, "host", client.SourceRDNS)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
clients.setWHOISInfo(ip, whois)
|
clients.setWHOISInfo(ip, whois)
|
||||||
|
@ -282,7 +283,7 @@ func TestClientsAddExisting(t *testing.T) {
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
|
|
||||||
// Now add an auto-client with the same IP.
|
// 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)
|
assert.True(t, ok)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghalg"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghhttp"
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
"github.com/AdguardTeam/AdGuardHome/internal/filtering"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/schedule"
|
"github.com/AdguardTeam/AdGuardHome/internal/schedule"
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
"github.com/AdguardTeam/AdGuardHome/internal/whois"
|
||||||
|
@ -90,7 +91,7 @@ type runtimeClientJSON struct {
|
||||||
|
|
||||||
IP netip.Addr `json:"ip"`
|
IP netip.Addr `json:"ip"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Source clientSource `json:"source"`
|
Source client.Source `json:"source"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type clientListJSON struct {
|
type clientListJSON struct {
|
||||||
|
@ -126,7 +127,7 @@ func (clients *clientsContainer) handleGetClients(w http.ResponseWriter, r *http
|
||||||
for _, l := range clients.dhcp.Leases() {
|
for _, l := range clients.dhcp.Leases() {
|
||||||
cj := runtimeClientJSON{
|
cj := runtimeClientJSON{
|
||||||
Name: l.Hostname,
|
Name: l.Hostname,
|
||||||
Source: ClientSourceDHCP,
|
Source: client.SourceDHCP,
|
||||||
IP: l.IP,
|
IP: l.IP,
|
||||||
WHOIS: &whois.Info{},
|
WHOIS: &whois.Info{},
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue