//go:build darwin || freebsd || linux || openbsd package dhcpd import ( "net" "net/netip" "path/filepath" "testing" "time" "github.com/AdguardTeam/AdGuardHome/internal/dhcpsvc" "github.com/AdguardTeam/golibs/testutil" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/exp/slices" ) func TestMain(m *testing.M) { testutil.DiscardLogOutput(m) } func testNotify(flags uint32) { } // Leases database store/load. func TestDB(t *testing.T) { var err error s := server{ conf: &ServerConfig{ dbFilePath: filepath.Join(t.TempDir(), dataFilename), }, } s.srv4, err = v4Create(&V4ServerConf{ Enabled: true, RangeStart: netip.MustParseAddr("192.168.10.100"), RangeEnd: netip.MustParseAddr("192.168.10.200"), GatewayIP: netip.MustParseAddr("192.168.10.1"), SubnetMask: netip.MustParseAddr("255.255.255.0"), notify: testNotify, }) require.NoError(t, err) s.srv6, err = v6Create(V6ServerConf{}) require.NoError(t, err) leases := []*dhcpsvc.Lease{{ Expiry: time.Now().Add(time.Hour), Hostname: "static-1.local", HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA}, IP: netip.MustParseAddr("192.168.10.100"), }, { Hostname: "static-2.local", HWAddr: net.HardwareAddr{0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xBB}, IP: netip.MustParseAddr("192.168.10.101"), }} srv4, ok := s.srv4.(*v4Server) require.True(t, ok) err = srv4.addLease(leases[0]) require.NoError(t, err) err = s.srv4.AddStaticLease(leases[1]) require.NoError(t, err) err = s.dbStore() require.NoError(t, err) err = s.srv4.ResetLeases(nil) require.NoError(t, err) err = s.dbLoad() require.NoError(t, err) ll := s.srv4.GetLeases(LeasesAll) require.Len(t, ll, len(leases)) assert.Equal(t, leases[0].HWAddr, ll[0].HWAddr) assert.Equal(t, leases[0].IP, ll[0].IP) assert.Equal(t, leases[0].Expiry.Unix(), ll[0].Expiry.Unix()) assert.Equal(t, leases[1].HWAddr, ll[1].HWAddr) assert.Equal(t, leases[1].IP, ll[1].IP) assert.True(t, ll[1].IsStatic) } func TestV4Server_badRange(t *testing.T) { testCases := []struct { name string gatewayIP netip.Addr subnetMask netip.Addr wantErrMsg string }{{ name: "gateway_in_range", gatewayIP: netip.MustParseAddr("192.168.10.120"), subnetMask: netip.MustParseAddr("255.255.255.0"), wantErrMsg: "dhcpv4: gateway ip 192.168.10.120 in the ip range: " + "192.168.10.20-192.168.10.200", }, { name: "outside_range_start", gatewayIP: netip.MustParseAddr("192.168.10.1"), subnetMask: netip.MustParseAddr("255.255.255.240"), wantErrMsg: "dhcpv4: range start 192.168.10.20 is outside network " + "192.168.10.1/28", }, { name: "outside_range_end", gatewayIP: netip.MustParseAddr("192.168.10.1"), subnetMask: netip.MustParseAddr("255.255.255.224"), wantErrMsg: "dhcpv4: range end 192.168.10.200 is outside network " + "192.168.10.1/27", }} for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { conf := V4ServerConf{ Enabled: true, RangeStart: netip.MustParseAddr("192.168.10.20"), RangeEnd: netip.MustParseAddr("192.168.10.200"), GatewayIP: tc.gatewayIP, SubnetMask: tc.subnetMask, notify: testNotify, } _, err := v4Create(&conf) testutil.AssertErrorMsg(t, tc.wantErrMsg, err) }) } } // cloneUDPAddr returns a deep copy of a. func cloneUDPAddr(a *net.UDPAddr) (clone *net.UDPAddr) { return &net.UDPAddr{ IP: slices.Clone(a.IP), Port: a.Port, Zone: a.Zone, } }