- A subnet is a deny-list subnet (the default: everyone not denied) or
an allow-list subnet (only clients allowed or with a reservation);
the deny list counts in both. Entries are MAC addresses, prefixes
(aa:bb:cc:*) or client IDs. A refused client gets no answer (DENIED
in the activity log, with an Allow button) or a NAK on renewal.
steward access, the subnet's Access tab. Schema migration 7.
- The activity log keeps each message's header fields and options,
decoded into words (dhcp4.Describe): the parameter request list by
name, client IDs, lease times. ▸ on an Activity row, steward
activity show N / --details, GET /events/{id}.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
37 lines
1.2 KiB
Go
37 lines
1.2 KiB
Go
package dhcp4
|
|
|
|
import (
|
|
"net"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestDescribe(t *testing.T) {
|
|
p := NewRequest(Discover, net.HardwareAddr{0xaa, 0, 0, 0, 0, 1}, 0x1234)
|
|
p.Set(OptParamRequest, []byte{1, 3, 6, 224})
|
|
p.Set(OptClientID, []byte{1, 0xaa, 0, 0, 0, 0, 1})
|
|
p.Set(OptLeaseTime, U32(5400))
|
|
p.Set(81, []byte{0x05, 0, 0, 6, 'l', 'a', 'p', 't', 'o', 'p', 0})
|
|
fields, opts := p.Describe()
|
|
got := map[string]string{}
|
|
for _, f := range append(fields, opts...) {
|
|
got[f.Name] = f.Value
|
|
}
|
|
for name, want := range map[string]string{
|
|
"transaction ID": "0x00001234",
|
|
"message-type": "DHCPDISCOVER",
|
|
"parameter-request-list": "subnet-mask (1), routers (3), domain-name-servers (6), option-224 (224)",
|
|
"client-identifier": "01:aa:00:00:00:00:01 (type 1: the MAC address aa:00:00:00:00:01)",
|
|
"lease-time": "5400 s (1h30m)",
|
|
"client-fqdn": "laptop (server updates the A record)",
|
|
"client hardware address": "aa:00:00:00:00:01",
|
|
} {
|
|
if !strings.EqualFold(got[name], want) {
|
|
t.Errorf("%s: %q, want %q", name, got[name], want)
|
|
}
|
|
}
|
|
if shortDuration(7*24*3600e9) != "7d" || shortDuration(90e9) != "1m30s" || shortDuration(43200e9) != "12h" {
|
|
t.Error("shortDuration")
|
|
}
|
|
}
|