From: Tomek Mrugalski Date: Mon, 3 Feb 2014 20:42:55 +0000 (+0100) Subject: [3274] Client classification for v6 implemented in CfgMgr X-Git-Tag: bind10-1.2.0beta1-release~57^2~1^2~11 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=290530e1c74db41d9dbf5e3dd733699345e7df2b;p=thirdparty%2Fkea.git [3274] Client classification for v6 implemented in CfgMgr --- diff --git a/src/lib/dhcpsrv/cfgmgr.cc b/src/lib/dhcpsrv/cfgmgr.cc index 4baaa02b23..3d2e87b6ce 100644 --- a/src/lib/dhcpsrv/cfgmgr.cc +++ b/src/lib/dhcpsrv/cfgmgr.cc @@ -123,7 +123,7 @@ CfgMgr::getOptionDef(const std::string& option_space, Subnet6Ptr CfgMgr::getSubnet6(const std::string& iface, - const isc::dhcp::ClientClasses& /*classes*/) { + const isc::dhcp::ClientClasses& classes) { if (!iface.length()) { return (Subnet6Ptr()); @@ -132,6 +132,12 @@ CfgMgr::getSubnet6(const std::string& iface, // If there is more than one, we need to choose the proper one for (Subnet6Collection::iterator subnet = subnets6_.begin(); subnet != subnets6_.end(); ++subnet) { + + // If client is rejected because of not meeting client class criteria... + if (!(*subnet)->clientSupported(classes)) { + continue; + } + if (iface == (*subnet)->getIface()) { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_SUBNET6_IFACE) @@ -144,7 +150,7 @@ CfgMgr::getSubnet6(const std::string& iface, Subnet6Ptr CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint, - const isc::dhcp::ClientClasses& /*classes*/) { + const isc::dhcp::ClientClasses& classes) { // If there's only one subnet configured, let's just use it // The idea is to keep small deployments easy. In a small network - one @@ -165,6 +171,11 @@ CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint, for (Subnet6Collection::iterator subnet = subnets6_.begin(); subnet != subnets6_.end(); ++subnet) { + // If client is rejected because of not meeting client class criteria... + if (!(*subnet)->clientSupported(classes)) { + continue; + } + if ((*subnet)->inRange(hint)) { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, DHCPSRV_CFGMGR_SUBNET6) @@ -180,7 +191,7 @@ CfgMgr::getSubnet6(const isc::asiolink::IOAddress& hint, } Subnet6Ptr CfgMgr::getSubnet6(OptionPtr iface_id_option, - const isc::dhcp::ClientClasses& /*classes*/) { + const isc::dhcp::ClientClasses& classes) { if (!iface_id_option) { return (Subnet6Ptr()); } @@ -189,6 +200,12 @@ Subnet6Ptr CfgMgr::getSubnet6(OptionPtr iface_id_option, // defined, check if the interface-id is equal to what we are looking for for (Subnet6Collection::iterator subnet = subnets6_.begin(); subnet != subnets6_.end(); ++subnet) { + + // If client is rejected because of not meeting client class criteria... + if (!(*subnet)->clientSupported(classes)) { + continue; + } + if ( (*subnet)->getInterfaceId() && ((*subnet)->getInterfaceId()->equal(iface_id_option))) { LOG_DEBUG(dhcpsrv_logger, DHCPSRV_DBG_TRACE, diff --git a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc index f7689c9f0d..31db594bdc 100644 --- a/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc +++ b/src/lib/dhcpsrv/tests/cfgmgr_unittest.cc @@ -427,6 +427,156 @@ TEST_F(CfgMgrTest, classifySubnet4) { EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_)); EXPECT_EQ(subnet2, cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_)); EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_)); + + // Now let's check that client with wrong class is not supported + classify_.clear(); + classify_.insert("some_other_class"); + EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_)); + + // Finally, let's check that client without any classes is not supported + classify_.clear(); + EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.5"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.70"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet4(IOAddress("192.0.2.130"), classify_)); +} + +// This test verifies if the configuration manager is able to hold and return +// valid leases +TEST_F(CfgMgrTest, classifySubnet6) { + CfgMgr& cfg_mgr = CfgMgr::instance(); + + // Let's configure 3 subnets + Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); + Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); + Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); + + cfg_mgr.addSubnet6(subnet1); + cfg_mgr.addSubnet6(subnet2); + cfg_mgr.addSubnet6(subnet3); + + // Let's sanity check that we can use that configuration. + EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); + EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); + EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); + + // Client now belongs to bar class. + classify_.insert("bar"); + + // There are no class restrictions defined, so everything should work + // as before + EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); + EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); + EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); + + // Now let's add client class restrictions. + subnet1->allowClientClass("foo"); // Serve here only clients from foo class + subnet2->allowClientClass("bar"); // Serve here only clients from bar class + subnet3->allowClientClass("baz"); // Serve here only clients from baz class + + // The same check as above should result in client being served only in + // bar class, i.e. subnet2 + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); + EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); + + // Now let's check that client with wrong class is not supported + classify_.clear(); + classify_.insert("some_other_class"); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); + + // Finally, let's check that client without any classes is not supported + classify_.clear(); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::345"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::567"), classify_)); +} + +// This test verifies if the configuration manager is able to hold, select +// and return valid subnets, based on interface names along with client +// classification. +TEST_F(CfgMgrTest, classifySubnet6Interface) { + CfgMgr& cfg_mgr = CfgMgr::instance(); + + // Let's have an odd configuration: 3 shared subnets available on the + // same direct link. + Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); + Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); + Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); + subnet1->setIface("foo"); + subnet2->setIface("foo"); + subnet3->setIface("foo"); + cfg_mgr.addSubnet6(subnet1); + cfg_mgr.addSubnet6(subnet2); + cfg_mgr.addSubnet6(subnet3); + + + // Regular client should get the first subnet, because it meets all + // criteria (matching interface name, no class restrictions. + EXPECT_EQ(subnet1, cfg_mgr.getSubnet6("foo", classify_)); + + // Now let's add class requirements for subnet1 + subnet1->allowClientClass("alpha"); + + // Client should now get the subnet2, because he no longer meets + // requirements for subnet1 (belongs to wrong class) + EXPECT_EQ(subnet2, cfg_mgr.getSubnet6("foo", classify_)); + + // Now let's add (not matching) classes to the other two subnets + subnet2->allowClientClass("beta"); + subnet3->allowClientClass("gamma"); + + // No subnets are suitable, so nothing will be selected + EXPECT_FALSE(cfg_mgr.getSubnet6("foo", classify_)); + + // Ok, let's add the client to gamme class, so he'll get a subnet + classify_.insert("gamma"); + EXPECT_EQ(subnet3, cfg_mgr.getSubnet6("foo", classify_)); +} + +// This test verifies if the configuration manager is able to hold, select +// and return valid subnets, based on interface-id option inserted by relay, +// along with client classification. +TEST_F(CfgMgrTest, classifySubnet6InterfaceId) { + CfgMgr& cfg_mgr = CfgMgr::instance(); + + // Let's have an odd configuration: 3 shared subnets available via the + // same remote relay with the same interface-id. + Subnet6Ptr subnet1(new Subnet6(IOAddress("2000::"), 48, 1, 2, 3, 4)); + Subnet6Ptr subnet2(new Subnet6(IOAddress("3000::"), 48, 1, 2, 3, 4)); + Subnet6Ptr subnet3(new Subnet6(IOAddress("4000::"), 48, 1, 2, 3, 4)); + OptionPtr ifaceid = generateInterfaceId("relay1.eth0"); + subnet1->setInterfaceId(ifaceid); + subnet2->setInterfaceId(ifaceid); + subnet3->setInterfaceId(ifaceid); + cfg_mgr.addSubnet6(subnet1); + cfg_mgr.addSubnet6(subnet2); + cfg_mgr.addSubnet6(subnet3); + + // Regular client should get the first subnet, because it meets all + // criteria (matching interface name, no class restrictions. + EXPECT_EQ(subnet1, cfg_mgr.getSubnet6(ifaceid, classify_)); + + // Now let's add class requirements for subnet1 + subnet1->allowClientClass("alpha"); + + // Client should now get the subnet2, because he no longer meets + // requirements for subnet1 (belongs to wrong class) + EXPECT_EQ(subnet2, cfg_mgr.getSubnet6(ifaceid, classify_)); + + // Now let's add (not matching) classes to the other two subnets + subnet2->allowClientClass("beta"); + subnet3->allowClientClass("gamma"); + + // No subnets are suitable, so nothing will be selected + EXPECT_FALSE(cfg_mgr.getSubnet6(ifaceid, classify_)); + + // Ok, let's add the client to gamme class, so he'll get a subnet + classify_.insert("gamma"); + EXPECT_EQ(subnet3, cfg_mgr.getSubnet6(ifaceid, classify_)); } // This test verifies if the configuration manager is able to hold and return @@ -461,7 +611,7 @@ TEST_F(CfgMgrTest, subnet6) { // Check that deletion of the subnets works. cfg_mgr.deleteSubnets6(); - EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("200::123"), classify_)); + EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("2000::123"), classify_)); EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("3000::123"), classify_)); EXPECT_FALSE(cfg_mgr.getSubnet6(IOAddress("4000::123"), classify_)); }