dhcp4d: display active devices based on LastACK
This has the advantage that it also works for static DHCP leases, provided the device obtains a DHCP lease at all (and isn’t configured with a static IP address, like the shelly motion sensors for example).
This commit is contained in:
parent
593cd8c12d
commit
2014da4ca3
@ -92,6 +92,9 @@ var (
|
||||
}
|
||||
return dur.Truncate(1 * time.Second).String()
|
||||
},
|
||||
"zero": func(t time.Time) bool {
|
||||
return t.IsZero()
|
||||
},
|
||||
}).Parse(`<!DOCTYPE html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@ -150,7 +153,7 @@ form {
|
||||
<th>Hostname</th>
|
||||
<th>MAC address</th>
|
||||
<th>Vendor</th>
|
||||
<th>Expiry</th>
|
||||
<th>Last ACK</th>
|
||||
</tr>
|
||||
{{ range $idx, $l := . }}
|
||||
<tr>
|
||||
@ -166,27 +169,31 @@ form {
|
||||
</td>
|
||||
<td class="hwaddr">{{$l.HardwareAddr}}</td>
|
||||
<td>{{$l.Vendor}}</td>
|
||||
<td title="{{ timefmt $l.Expiry }}">
|
||||
{{ if $l.Expired }}
|
||||
{{ since $l.Expiry }}
|
||||
<span class="expired">expired</span>
|
||||
{{ else }}
|
||||
{{ if $l.Static }}
|
||||
<span class="static">static</span>
|
||||
{{ else }}
|
||||
{{ timefmt $l.Expiry }}
|
||||
<td>
|
||||
{{ if (not (zero $l.LastACK)) }}
|
||||
{{ timefmt $l.LastACK }}
|
||||
{{ if $l.Active }}
|
||||
<span class="active">active</span>
|
||||
{{ end }}
|
||||
{{ if $l.Expired }}
|
||||
<span class="expired">expired</span>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</td>
|
||||
</tr>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
|
||||
<h1>Static Leases</h1>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
{{ template "table" .StaticLeases }}
|
||||
</table>
|
||||
|
||||
<h1>Dynamic Leases</h1>
|
||||
<table cellpadding="0" cellspacing="0">
|
||||
{{ template "table" .DynamicLeases }}
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
`))
|
||||
@ -341,17 +348,20 @@ func newSrv(permDir string) (*srv, error) {
|
||||
Vendor string
|
||||
Expired bool
|
||||
Static bool
|
||||
Active bool
|
||||
}
|
||||
|
||||
leasesMu.Lock()
|
||||
defer leasesMu.Unlock()
|
||||
static := make([]tmplLease, 0, len(leases))
|
||||
dynamic := make([]tmplLease, 0, len(leases))
|
||||
now := time.Now()
|
||||
tl := func(l *dhcp4d.Lease) tmplLease {
|
||||
return tmplLease{
|
||||
Lease: *l,
|
||||
Vendor: ouiDB.Lookup(l.HardwareAddr[:8]),
|
||||
Expired: l.Expired(time.Now()),
|
||||
Expired: l.Expired(now),
|
||||
Active: l.Active(now),
|
||||
Static: l.Expiry.IsZero(),
|
||||
}
|
||||
}
|
||||
|
@ -43,12 +43,17 @@ type Lease struct {
|
||||
Hostname string `json:"hostname"`
|
||||
HostnameOverride string `json:"hostname_override"`
|
||||
Expiry time.Time `json:"expiry"`
|
||||
LastACK time.Time `json:"last_ack"`
|
||||
}
|
||||
|
||||
func (l *Lease) Expired(at time.Time) bool {
|
||||
return !l.Expiry.IsZero() && at.After(l.Expiry)
|
||||
}
|
||||
|
||||
func (l *Lease) Active(at time.Time) bool {
|
||||
return !l.LastACK.IsZero() && at.Before(l.LastACK.Add(leasePeriod))
|
||||
}
|
||||
|
||||
type Handler struct {
|
||||
serverIP net.IP
|
||||
start net.IP // first IP address to hand out
|
||||
@ -90,18 +95,14 @@ func NewHandler(dir string, iface *net.Interface, ifaceName string, conn net.Pac
|
||||
copy(start, serverIP)
|
||||
start[len(start)-1] += 1
|
||||
return &Handler{
|
||||
rawConn: conn,
|
||||
iface: iface,
|
||||
leasesHW: make(map[string]int),
|
||||
leasesIP: make(map[int]*Lease),
|
||||
serverIP: serverIP,
|
||||
start: start,
|
||||
leaseRange: 230,
|
||||
// Apple recommends a DHCP lease time of 1 hour in
|
||||
// https://support.apple.com/de-ch/HT202068,
|
||||
// so if 20 minutes ever causes any trouble,
|
||||
// we should try increasing it to 1 hour.
|
||||
LeasePeriod: 20 * time.Minute,
|
||||
rawConn: conn,
|
||||
iface: iface,
|
||||
leasesHW: make(map[string]int),
|
||||
leasesIP: make(map[int]*Lease),
|
||||
serverIP: serverIP,
|
||||
start: start,
|
||||
leaseRange: 230,
|
||||
LeasePeriod: leasePeriod,
|
||||
options: dhcp4.Options{
|
||||
dhcp4.OptionSubnetMask: []byte{255, 255, 255, 0},
|
||||
dhcp4.OptionRouter: []byte(serverIP),
|
||||
@ -113,6 +114,12 @@ func NewHandler(dir string, iface *net.Interface, ifaceName string, conn net.Pac
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Apple recommends a DHCP lease time of 1 hour in
|
||||
// https://support.apple.com/de-ch/HT202068,
|
||||
// so if 20 minutes ever causes any trouble,
|
||||
// we should try increasing it to 1 hour.
|
||||
const leasePeriod = 20 * time.Minute
|
||||
|
||||
// SetLeases overwrites the leases database with the specified leases, typically
|
||||
// loaded from persistent storage. There is no locking, so SetLeases must be
|
||||
// called before Serve.
|
||||
@ -122,6 +129,9 @@ func (h *Handler) SetLeases(leases []*Lease) {
|
||||
h.leasesHW = make(map[string]int)
|
||||
h.leasesIP = make(map[int]*Lease)
|
||||
for _, l := range leases {
|
||||
if l.LastACK.IsZero() {
|
||||
l.LastACK = l.Expiry
|
||||
}
|
||||
h.leasesHW[l.HardwareAddr] = l.Num
|
||||
h.leasesIP[l.Num] = l
|
||||
}
|
||||
@ -334,6 +344,7 @@ func (h *Handler) serveDHCP(p dhcp4.Packet, msgType dhcp4.MessageType, options d
|
||||
HardwareAddr: hwAddr,
|
||||
Expiry: h.timeNow().Add(h.leasePeriodForDevice(hwAddr)),
|
||||
Hostname: string(options[dhcp4.OptionHostName]),
|
||||
LastACK: h.timeNow(),
|
||||
}
|
||||
copy(lease.Addr, reqIP.To4())
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user