Skip to content

Commit 87bbe9e

Browse files
committed
Pull request 2575: 4923-gopacket-dhcp-vol.19
Updates #4923. Squashed commit of the following: commit 01ccbfb2cc73904b00d3ef6feb488521c6fc08b3 Merge: 277b819fd d66443b Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Feb 4 16:20:14 2026 +0300 Merge branch 'master' into 4923-gopacket-dhcp-vol.19 commit 277b819fd8fe596e2917f8a2b1d924c0a18830cd Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Wed Feb 4 14:38:35 2026 +0300 dhcpsvc: imp test code commit 172d2e33e0ed84ea373e5936e310fe7937adcd59 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Tue Feb 3 16:38:54 2026 +0300 dhcpsvc: fix decline behavior commit ba3d051c2dfa397a4ada39f913d12fbfed9d0b14 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Tue Feb 3 15:56:57 2026 +0300 dhcpsvc: add decline test commit defa4e00458c6c83b07069b1153b8a188108fbc9 Author: Eugene Burkov <E.Burkov@AdGuard.COM> Date: Thu Jan 29 17:51:03 2026 +0300 dhcpsvc: imp tests
1 parent d66443b commit 87bbe9e

23 files changed

Lines changed: 477 additions & 172 deletions

File tree

internal/dhcpsvc/config_test.go

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -57,40 +57,41 @@ func TestIPv4Config_Validate(t *testing.T) {
5757
conf: &dhcpsvc.IPv4Config{
5858
Enabled: true,
5959
Clock: testIPv4Conf.Clock,
60-
GatewayIP: netip.MustParseAddr("2001:db8::1"),
60+
GatewayIP: netip.MustParseAddr(testRangeStartV6Str),
6161
SubnetMask: testIPv4Conf.SubnetMask,
6262
RangeStart: testIPv4Conf.RangeStart,
6363
RangeEnd: testIPv4Conf.RangeEnd,
6464
LeaseDuration: testIPv4Conf.LeaseDuration,
6565
},
66-
wantErrMsg: "gateway ip 2001:db8::1 must be a valid ipv4" + "\n" +
67-
"range start 192.168.0.100 is not within 2001:db8::1/24",
66+
wantErrMsg: "gateway ip " + testRangeStartV6Str + " must be a valid ipv4" + "\n" +
67+
"range start " + testRangeStartV4Str + " is not within " + testRangeStartV6Str + "/24",
6868
}, {
6969
name: "bad_subnet_mask",
7070
conf: &dhcpsvc.IPv4Config{
7171
Enabled: true,
7272
Clock: testIPv4Conf.Clock,
7373
GatewayIP: testIPv4Conf.GatewayIP,
74-
SubnetMask: netip.MustParseAddr("2001:db8::1"),
74+
SubnetMask: netip.MustParseAddr(testRangeStartV6Str),
7575
RangeStart: testIPv4Conf.RangeStart,
7676
RangeEnd: testIPv4Conf.RangeEnd,
7777
LeaseDuration: testIPv4Conf.LeaseDuration,
7878
},
79-
wantErrMsg: "subnet mask 2001:db8::1 must be a valid ipv4 cidr mask",
79+
wantErrMsg: "subnet mask " + testRangeStartV6Str + " must be a valid ipv4 cidr mask",
8080
}, {
8181
name: "bad_range_start",
8282
conf: &dhcpsvc.IPv4Config{
8383
Enabled: true,
8484
Clock: testIPv4Conf.Clock,
8585
GatewayIP: testIPv4Conf.GatewayIP,
8686
SubnetMask: testIPv4Conf.SubnetMask,
87-
RangeStart: netip.MustParseAddr("2001:db8::1"),
87+
RangeStart: netip.MustParseAddr(testRangeStartV6Str),
8888
RangeEnd: testIPv4Conf.RangeEnd,
8989
LeaseDuration: testIPv4Conf.LeaseDuration,
9090
},
91-
wantErrMsg: "range start 2001:db8::1 must be a valid ipv4" + "\n" +
92-
"range start 2001:db8::1 is not within 192.168.0.1/24" + "\n" +
93-
"invalid ip range: 2001:db8::1 and 192.168.0.200 must be within the same address family",
91+
wantErrMsg: "range start " + testRangeStartV6Str + " must be a valid ipv4" + "\n" +
92+
"range start " + testRangeStartV6Str + " is not within " +
93+
testGatewayIPv4Str + "/24" + "\n" + "invalid ip range: " + testRangeStartV6Str +
94+
" and " + testRangeEndV4Str + " must be within the same address family",
9495
}, {
9596
name: "bad_range_end",
9697
conf: &dhcpsvc.IPv4Config{
@@ -99,12 +100,13 @@ func TestIPv4Config_Validate(t *testing.T) {
99100
GatewayIP: testIPv4Conf.GatewayIP,
100101
SubnetMask: testIPv4Conf.SubnetMask,
101102
RangeStart: testIPv4Conf.RangeStart,
102-
RangeEnd: netip.MustParseAddr("2001:db8::1"),
103+
RangeEnd: netip.MustParseAddr(testRangeStartV6Str),
103104
LeaseDuration: testIPv4Conf.LeaseDuration,
104105
},
105-
wantErrMsg: "range end 2001:db8::1 must be a valid ipv4" + "\n" +
106-
"range end 2001:db8::1 is not within 192.168.0.1/24" + "\n" +
107-
"invalid ip range: 192.168.0.100 and 2001:db8::1 must be within the same address family",
106+
wantErrMsg: "range end " + testRangeStartV6Str + " must be a valid ipv4" + "\n" +
107+
"range end " + testRangeStartV6Str + " is not within " + testGatewayIPv4Str + "/24" +
108+
"\n" + "invalid ip range: " + testRangeStartV4Str + " and " + testRangeStartV6Str +
109+
" must be within the same address family",
108110
}}
109111

110112
for _, tc := range testCases {
@@ -135,23 +137,23 @@ func TestIPv6Config_Validate(t *testing.T) {
135137
name: "bad_range_start",
136138
conf: &dhcpsvc.IPv6Config{
137139
Enabled: true,
138-
RangeStart: netip.MustParseAddr("192.168.0.1"),
140+
RangeStart: testIPv4Conf.GatewayIP,
139141
LeaseDuration: 1 * time.Hour,
140142
},
141-
wantErrMsg: "range start 192.168.0.1 should be a valid ipv6",
143+
wantErrMsg: "range start " + testGatewayIPv4Str + " should be a valid ipv6",
142144
}, {
143145
name: "bad_lease_duration",
144146
conf: &dhcpsvc.IPv6Config{
145147
Enabled: true,
146-
RangeStart: netip.MustParseAddr("2001:db8::1"),
148+
RangeStart: netip.MustParseAddr(testRangeStartV6Str),
147149
LeaseDuration: 0,
148150
},
149151
wantErrMsg: "lease duration 0s must be positive",
150152
}, {
151153
name: "valid",
152154
conf: &dhcpsvc.IPv6Config{
153155
Enabled: true,
154-
RangeStart: netip.MustParseAddr("2001:db8::1"),
156+
RangeStart: netip.MustParseAddr(testRangeStartV6Str),
155157
LeaseDuration: 1 * time.Hour,
156158
},
157159
wantErrMsg: "",
@@ -174,7 +176,7 @@ func TestConfig_Validate(t *testing.T) {
174176
NetworkDeviceManager: dhcpsvc.EmptyNetworkDeviceManager{},
175177
Logger: testLogger,
176178
LocalDomainName: testLocalTLD,
177-
DBFilePath: filepath.Join(t.TempDir(), "leases.json"),
179+
DBFilePath: filepath.Join(t.TempDir(), testDBLeasesFilename),
178180
ICMPTimeout: 1 * time.Second,
179181
Enabled: true,
180182
}

internal/dhcpsvc/dhcpsvc_test.go

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ const testLocalTLD = "local"
3131
// testIfaceName is the name of the test network interface.
3232
const testIfaceName = "iface0"
3333

34+
// testDBLeasesFilename is the common name of a leases database file for tests.
35+
const testDBLeasesFilename = "leases.json"
36+
3437
// testTimeout is a common timeout for tests and contexts.
3538
const testTimeout = 10 * time.Second
3639

@@ -57,23 +60,71 @@ var testClock = &faketime.Clock{
5760
},
5861
}
5962

63+
const (
64+
// testGatewayIPv4Str is the string representation of the gateway IPv4
65+
// address used in tests.
66+
testGatewayIPv4Str = "192.0.2.1"
67+
68+
// testSubnetMaskV4Str is the string representation of the subnet mask for
69+
// the IPv4 interface used in tests.
70+
testSubnetMaskV4Str = "255.255.255.0"
71+
72+
// testRangeStartV4Str is the string representation of the range start of
73+
// the IPv4 interface used in tests.
74+
testRangeStartV4Str = "192.0.2.100"
75+
76+
// testRangeEndV4Str is the string representation of the range end of the
77+
// IPv4 interface used in tests.
78+
testRangeEndV4Str = "192.0.2.200"
79+
80+
// testIfaceAddrV4Str is the string representation of the interface's IPv4
81+
// address used in tests.
82+
testIfaceAddrV4Str = "192.0.2.2"
83+
84+
// testAnotherGatewayIPv4Str is the string representation of the second
85+
// gateway IPv4 address used in tests.
86+
testAnotherGatewayIPv4Str = "198.51.100.1"
87+
88+
// testAnotherSubnetMaskV4Str is the string representation of the subnet
89+
// mask for the second IPv4 interface used in tests.
90+
testAnotherSubnetMaskV4Str = "255.255.255.0"
91+
92+
// testAnotherRangeStartV4Str is the string representation of the range
93+
// start of the second IPv4 interface used in tests.
94+
testAnotherRangeStartV4Str = "198.51.100.100"
95+
96+
// testAnotherRangeEndV4Str is the string representation of the range end
97+
// of the second IPv4 interface used in tests.
98+
testAnotherRangeEndV4Str = "198.51.100.200"
99+
)
100+
101+
const (
102+
// testRangeStartV6Str is the string representation of the range start of
103+
// the IPv6 interface used in tests.
104+
testRangeStartV6Str = "2001:db8::1"
105+
106+
// testAnotherRangeStartV6Str is the string representation of the range
107+
// start of the second IPv6 interface used in tests.
108+
testAnotherRangeStartV6Str = "2001:db9::1"
109+
)
110+
60111
var (
61112
// testIPv4Conf is a common valid IPv4 part of the interface configuration
62113
// for tests.
63114
testIPv4Conf = &dhcpsvc.IPv4Config{
64115
Clock: testClock,
65-
GatewayIP: netip.MustParseAddr("192.168.0.1"),
66-
SubnetMask: netip.MustParseAddr("255.255.255.0"),
67-
RangeStart: netip.MustParseAddr("192.168.0.100"),
68-
RangeEnd: netip.MustParseAddr("192.168.0.200"),
116+
GatewayIP: netip.MustParseAddr(testGatewayIPv4Str),
117+
SubnetMask: netip.MustParseAddr(testSubnetMaskV4Str),
118+
RangeStart: netip.MustParseAddr(testRangeStartV4Str),
119+
RangeEnd: netip.MustParseAddr(testRangeEndV4Str),
69120
LeaseDuration: testLeaseTTL,
70121
Enabled: true,
71122
}
72123

73124
// testIfaceAddr is a common valid IPv4 address of the test network
74125
// interface, compliant with [testIPv4Conf], i.e. outside of the range,
75126
// within the subnet, not equal to the gateway.
76-
testIfaceAddr = netip.MustParseAddr("192.168.0.2")
127+
testIfaceAddr = netip.MustParseAddr(testIfaceAddrV4Str)
77128

78129
// testIfaceHWAddr is a common valid hardware address of the test network
79130
// interface.
@@ -84,7 +135,7 @@ var (
84135
// tests.
85136
var testIPv6Conf = &dhcpsvc.IPv6Config{
86137
Enabled: true,
87-
RangeStart: netip.MustParseAddr("2001:db8::1"),
138+
RangeStart: netip.MustParseAddr(testRangeStartV6Str),
88139
LeaseDuration: testLeaseTTL,
89140
RAAllowSLAAC: true,
90141
RASLAACOnly: true,
@@ -101,15 +152,15 @@ var testInterfaceConf = map[string]*dhcpsvc.InterfaceConfig{
101152
IPv4: &dhcpsvc.IPv4Config{
102153
Enabled: true,
103154
Clock: timeutil.SystemClock{},
104-
GatewayIP: netip.MustParseAddr("172.16.0.1"),
105-
SubnetMask: netip.MustParseAddr("255.255.255.0"),
106-
RangeStart: netip.MustParseAddr("172.16.0.100"),
107-
RangeEnd: netip.MustParseAddr("172.16.0.200"),
155+
GatewayIP: netip.MustParseAddr(testAnotherGatewayIPv4Str),
156+
SubnetMask: netip.MustParseAddr(testAnotherSubnetMaskV4Str),
157+
RangeStart: netip.MustParseAddr(testAnotherRangeStartV4Str),
158+
RangeEnd: netip.MustParseAddr(testAnotherRangeEndV4Str),
108159
LeaseDuration: 1 * time.Hour,
109160
},
110161
IPv6: &dhcpsvc.IPv6Config{
111162
Enabled: true,
112-
RangeStart: netip.MustParseAddr("2001:db9::100"),
163+
RangeStart: netip.MustParseAddr(testAnotherRangeStartV6Str),
113164
LeaseDuration: 1 * time.Hour,
114165
RAAllowSLAAC: true,
115166
RASLAACOnly: true,
@@ -136,12 +187,10 @@ var fullLayersStack = []gopacket.LayerType{
136187
func newTempDB(tb testing.TB) (dst string) {
137188
tb.Helper()
138189

139-
const filename = "leases.json"
140-
141-
data, err := fs.ReadFile(testdata, path.Join(tb.Name(), filename))
190+
data, err := fs.ReadFile(testdata, path.Join(tb.Name(), testDBLeasesFilename))
142191
require.NoError(tb, err)
143192

144-
dst = filepath.Join(tb.TempDir(), filename)
193+
dst = filepath.Join(tb.TempDir(), testDBLeasesFilename)
145194

146195
err = os.WriteFile(dst, data, 0o640)
147196
require.NoError(tb, err)

internal/dhcpsvc/handler4.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -358,14 +358,10 @@ func (iface *dhcpInterfaceV4) handleDecline(ctx context.Context, req *layers.DHC
358358

359359
l.WarnContext(ctx, "lease reported to be unavailable", "ip", lease.IP)
360360

361-
err := iface.common.index.remove(ctx, l, lease, iface.common)
361+
err := iface.common.blockLease(ctx, lease, iface.clock)
362362
if err != nil {
363-
l.ErrorContext(ctx, "removing lease", slogutil.KeyError, err)
364-
365-
return
363+
l.ErrorContext(ctx, "blocking lease", slogutil.KeyError, err)
366364
}
367-
368-
iface.common.blockLease(lease, iface.clock)
369365
}
370366

371367
// handleRelease handles messages of type DHCPRELEASE. req must be a

0 commit comments

Comments
 (0)