diff --git a/changelog_unreleased/4047-early-call-to-selectsubnet-with-sanity_only-true-alters-behavior-for-broadcast-clients b/changelog_unreleased/4047-early-call-to-selectsubnet-with-sanity_only-true-alters-behavior-for-broadcast-clients new file mode 100644 index 0000000000..b27e145e54 --- /dev/null +++ b/changelog_unreleased/4047-early-call-to-selectsubnet-with-sanity_only-true-alters-behavior-for-broadcast-clients @@ -0,0 +1,6 @@ +[bug] tmark + Corrected an issue in kea-dhcp4 which caused + broadcasted client queries to fail to match subnets + restricted to classes assigned during early global + host lookups. + (Gitlab #4047) diff --git a/src/bin/dhcp4/tests/classify_unittest.cc b/src/bin/dhcp4/tests/classify_unittest.cc index 29f5f97363..65d6014686 100644 --- a/src/bin/dhcp4/tests/classify_unittest.cc +++ b/src/bin/dhcp4/tests/classify_unittest.cc @@ -2371,7 +2371,7 @@ TEST_F(ClassifyTest, classTaggingList) { IfaceMgrTestConfig test_config(true); // Define a client-str option for classification, and server-str - // option to send in response. Then define 3 possible values in + // option to send in response. Then define 3 possible values in // a subnet for sever-str based on class membership. string config = R"^( { @@ -2431,8 +2431,8 @@ TEST_F(ClassifyTest, classTaggingList) { }; std::list scenarios { - { __LINE__, "one", "class-one", "string.one" }, - { __LINE__, "two", "class-two", "string.two" }, + { __LINE__, "one", "class-one", "string.one" }, + { __LINE__, "two", "class-two", "string.two" }, { __LINE__, "neither", "class-neither", "string.other" } }; @@ -2476,4 +2476,63 @@ TEST_F(ClassifyTest, classTaggingList) { } } +// This test verifies that a broadcast message can rely on +// early global reservations lookup for selecting a guarded subnet. +// This test uses a single guarded subnet to ensure that subnet +// selection doesn't have default. +TEST_F(ClassifyTest, earlySubnetNoFallback) { + Dhcp4Client client(srv_, Dhcp4Client::SELECTING); + + std::string config = + "{ \"interfaces-config\": {" + " \"interfaces\": [ \"*\" ]" + "}," + "\"valid-lifetime\": 600," + "\"early-global-reservations-lookup\": true," + "\"client-classes\": [" + "{" + " \"name\": \"only-one\"" + "}]," + "\"subnet4\": [" + "{" + " \"subnet\": \"10.0.0.0/24\"," + " \"id\": 1," + " \"interface\": \"eth0\"," + " \"pools\": [ { \"pool\": \"10.0.0.10-10.0.0.100\" } ]," + " \"client-class\": \"only-one\"" + "}" + "]," + "\"reservations\": [ {" + " \"hw-address\": \"aa:bb:cc:dd:ee:ff\"," + " \"client-classes\": [ \"only-one\" ] } ]" + "}"; + + // Configure DHCP server. + configure(config, *client.getServer()); + + // Set the HW address to the reservation. + client.setHWAddress("aa:bb:cc:dd:ee:ff"); + + // Send the discover. + client.doDiscover(); + + // Check response. + Pkt4Ptr resp = client.getContext().response_; + ASSERT_TRUE(resp); + EXPECT_EQ("10.0.0.10", resp->getYiaddr().toText()); + + // Try with a different HW address. + Dhcp4Client client2(srv_, Dhcp4Client::SELECTING); + + // Set the HW address to another value. This will not select a subnet. + client2.setHWAddress("aa:bb:cc:01:ee:ff"); + + // Send the discover. + client2.doDiscover(); + + // Check response. + resp = client2.getContext().response_; + ASSERT_FALSE(resp); +} + } // end of anonymous namespace