diff options
author | Andrei Pavel <andrei@isc.org> | 2021-05-18 16:24:39 +0200 |
---|---|---|
committer | Andrei Pavel <andrei@isc.org> | 2021-06-25 15:24:35 +0200 |
commit | 2a92725a1a531c5587cc5b98bd10cb19a98d6abc (patch) | |
tree | ad0220e79157db2c8743e7cf0a2f4d0ad3852060 /src | |
parent | [#1894] limit docsis oro lookup to cable labs 4491 (diff) | |
download | kea-2a92725a1a531c5587cc5b98bd10cb19a98d6abc.tar.xz kea-2a92725a1a531c5587cc5b98bd10cb19a98d6abc.zip |
[#1894] negative test for cable labs vendor ID
Diffstat (limited to 'src')
-rw-r--r-- | src/bin/dhcp4/tests/vendor_opts_unittest.cc | 196 | ||||
-rw-r--r-- | src/bin/dhcp6/tests/vendor_opts_unittest.cc | 211 |
2 files changed, 229 insertions, 178 deletions
diff --git a/src/bin/dhcp4/tests/vendor_opts_unittest.cc b/src/bin/dhcp4/tests/vendor_opts_unittest.cc index 1230f4cb3c..55fde87672 100644 --- a/src/bin/dhcp4/tests/vendor_opts_unittest.cc +++ b/src/bin/dhcp4/tests/vendor_opts_unittest.cc @@ -48,7 +48,110 @@ using namespace isc::dhcp::test; /// groups all vendor related tests under a single name. There were too many /// tests in Dhcpv4SrvTest class anyway. class VendorOptsTest : public Dhcpv4SrvTest { - +public: + void testVendorOptionsORO(int vendor_id) { + IfaceMgrTestConfig test_config(true); + IfaceMgr::instance().openSockets4(); + + NakedDhcpv4Srv srv(0); + + string config = R"( + { + "interfaces-config": { + "interfaces": [ "*" ] + }, + "option-data": [ + { + "code": 2, + "csv-format": true, + "data": "192.0.2.1, 192.0.2.2", + "name": "tftp-servers", + "space": "vendor-4491" + } + ], + "subnet4": [ + { + "interface": "eth0", + "pools": [ + { + "pool": "192.0.2.0/25" + } + ], + "subnet": "192.0.2.0/24" + } + ] + } + )"; + + ConstElementPtr json; + ASSERT_NO_THROW(json = parseDHCP4(config)); + + ConstElementPtr x; + EXPECT_NO_THROW(x = configureDhcp4Server(srv, json)); + ASSERT_TRUE(x); + comment_ = parseAnswer(rcode_, x); + ASSERT_EQ(0, rcode_); + + CfgMgr::instance().commit(); + + boost::shared_ptr<Pkt4> dis(new Pkt4(DHCPDISCOVER, 1234)); + // Set the giaddr and hops to non-zero address as if it was relayed. + dis->setGiaddr(IOAddress("192.0.2.1")); + dis->setHops(1); + + OptionPtr clientid = generateClientId(); + dis->addOption(clientid); + // Set interface. It is required by the server to generate server id. + dis->setIface("eth0"); + dis->setIndex(ETH0_INDEX); + + // Pass it to the server and get an advertise + Pkt4Ptr offer = srv.processDiscover(dis); + + // check if we get response at all + ASSERT_TRUE(offer); + + // We did not include any vendor opts in DISCOVER, so there should be none + // in OFFER. + ASSERT_FALSE(offer->getOption(DHO_VIVSO_SUBOPTIONS)); + + // Let's add a vendor-option (vendor-id=4491) with a single sub-option. + // That suboption has code 1 and is a docsis ORO option. + boost::shared_ptr<OptionUint8Array> vendor_oro(new OptionUint8Array(Option::V4, + DOCSIS3_V4_ORO)); + vendor_oro->addValue(DOCSIS3_V4_TFTP_SERVERS); // Request option 33 + OptionPtr vendor(new OptionVendor(Option::V4, vendor_id)); + vendor->addOption(vendor_oro); + dis->addOption(vendor); + + // Need to process SOLICIT again after requesting new option. + offer = srv.processDiscover(dis); + ASSERT_TRUE(offer); + + // Check if there is (or not) a vendor option in the response. + OptionPtr tmp = offer->getOption(DHO_VIVSO_SUBOPTIONS); + if (vendor_id != VENDOR_ID_CABLE_LABS) { + EXPECT_FALSE(tmp); + return; + } + ASSERT_TRUE(tmp); + + // The response should be OptionVendor object + boost::shared_ptr<OptionVendor> vendor_resp = + boost::dynamic_pointer_cast<OptionVendor>(tmp); + ASSERT_TRUE(vendor_resp); + + OptionPtr docsis2 = vendor_resp->getOption(DOCSIS3_V4_TFTP_SERVERS); + ASSERT_TRUE(docsis2); + + Option4AddrLstPtr tftp_srvs = boost::dynamic_pointer_cast<Option4AddrLst>(docsis2); + ASSERT_TRUE(tftp_srvs); + + Option4AddrLst::AddressContainer addrs = tftp_srvs->getAddresses(); + ASSERT_EQ(2, addrs.size()); + EXPECT_EQ("192.0.2.1", addrs[0].toText()); + EXPECT_EQ("192.0.2.2", addrs[1].toText()); + } }; /// @todo Add more extensive vendor options tests, including multiple @@ -184,92 +287,13 @@ TEST_F(VendorOptsTest, docsisVendorORO) { // This test checks if Option Request Option (ORO) in docsis (vendor-id=4491) // vendor options is parsed correctly and the requested options are actually assigned. TEST_F(VendorOptsTest, vendorOptionsORO) { - IfaceMgrTestConfig test_config(true); - IfaceMgr::instance().openSockets4(); - - NakedDhcpv4Srv srv(0); - - ConstElementPtr x; - string config = "{ \"interfaces-config\": {" - " \"interfaces\": [ \"*\" ]" - "}," - " \"option-data\": [ {" - " \"name\": \"tftp-servers\"," - " \"space\": \"vendor-4491\"," - " \"code\": 2," - " \"data\": \"192.0.2.1, 192.0.2.2\"," - " \"csv-format\": true" - " }]," - "\"subnet4\": [ { " - " \"pools\": [ { \"pool\": \"192.0.2.0/25\" } ]," - " \"subnet\": \"192.0.2.0/24\", " - " \"interface\": \"eth0\" " - " } ]" - "}"; - - ConstElementPtr json; - ASSERT_NO_THROW(json = parseDHCP4(config)); - - EXPECT_NO_THROW(x = configureDhcp4Server(srv, json)); - ASSERT_TRUE(x); - comment_ = parseAnswer(rcode_, x); - ASSERT_EQ(0, rcode_); - - CfgMgr::instance().commit(); - - boost::shared_ptr<Pkt4> dis(new Pkt4(DHCPDISCOVER, 1234)); - // Set the giaddr and hops to non-zero address as if it was relayed. - dis->setGiaddr(IOAddress("192.0.2.1")); - dis->setHops(1); - - OptionPtr clientid = generateClientId(); - dis->addOption(clientid); - // Set interface. It is required by the server to generate server id. - dis->setIface("eth0"); - dis->setIndex(ETH0_INDEX); - - // Pass it to the server and get an advertise - Pkt4Ptr offer = srv.processDiscover(dis); - - // check if we get response at all - ASSERT_TRUE(offer); - - // We did not include any vendor opts in DISCOVER, so there should be none - // in OFFER. - ASSERT_FALSE(offer->getOption(DHO_VIVSO_SUBOPTIONS)); - - // Let's add a vendor-option (vendor-id=4491) with a single sub-option. - // That suboption has code 1 and is a docsis ORO option. - boost::shared_ptr<OptionUint8Array> vendor_oro(new OptionUint8Array(Option::V4, - DOCSIS3_V4_ORO)); - vendor_oro->addValue(DOCSIS3_V4_TFTP_SERVERS); // Request option 33 - OptionPtr vendor(new OptionVendor(Option::V4, 4491)); - vendor->addOption(vendor_oro); - dis->addOption(vendor); - - // Need to process SOLICIT again after requesting new option. - offer = srv.processDiscover(dis); - ASSERT_TRUE(offer); - - // Check if there is a vendor option response - OptionPtr tmp = offer->getOption(DHO_VIVSO_SUBOPTIONS); - ASSERT_TRUE(tmp); - - // The response should be OptionVendor object - boost::shared_ptr<OptionVendor> vendor_resp = - boost::dynamic_pointer_cast<OptionVendor>(tmp); - ASSERT_TRUE(vendor_resp); - - OptionPtr docsis2 = vendor_resp->getOption(DOCSIS3_V4_TFTP_SERVERS); - ASSERT_TRUE(docsis2); - - Option4AddrLstPtr tftp_srvs = boost::dynamic_pointer_cast<Option4AddrLst>(docsis2); - ASSERT_TRUE(tftp_srvs); + testVendorOptionsORO(VENDOR_ID_CABLE_LABS); +} - Option4AddrLst::AddressContainer addrs = tftp_srvs->getAddresses(); - ASSERT_EQ(2, addrs.size()); - EXPECT_EQ("192.0.2.1", addrs[0].toText()); - EXPECT_EQ("192.0.2.2", addrs[1].toText()); +// Same as vendorOptionsORO except a different vendor ID than Cable Labs is +// provided and vendor options are expected to not be present in the response. +TEST_F(VendorOptsTest, vendorOptionsORODifferentVendorID) { + testVendorOptionsORO(32768); } // This test checks if Option Request Option (ORO) in docsis (vendor-id=4491) diff --git a/src/bin/dhcp6/tests/vendor_opts_unittest.cc b/src/bin/dhcp6/tests/vendor_opts_unittest.cc index 034592e74d..3e75074445 100644 --- a/src/bin/dhcp6/tests/vendor_opts_unittest.cc +++ b/src/bin/dhcp6/tests/vendor_opts_unittest.cc @@ -43,6 +43,113 @@ using namespace isc::asiolink; /// @brief Class dedicated to testing vendor options in DHCPv6 class VendorOptsTest : public Dhcpv6SrvTest { public: + void testVendorOptionsORO(int vendor_id) { + IfaceMgrTestConfig test_config(true); + + string config = R"( + { + "interfaces-config": { + "interfaces": [ "*" ] + }, + "option-data": [ + { + "data": "normal_erouter_v6.cm", + "name": "config-file", + "space": "vendor-4491" + } + ], + "option-def": [ + { + "code": 33, + "name": "config-file", + "space": "vendor-4491", + "type": "string" + } + ], + "preferred-lifetime": 3000, + "rebind-timer": 2000, + "renew-timer": 1000, + "subnet6": [ + { + "interface": "eth0", + "interface-id": "", + "pools": [ + { + "pool": "2001:db8:1::/64" + } + ], + "preferred-lifetime": 3000, + "rebind-timer": 1000, + "renew-timer": 1000, + "subnet": "2001:db8:1::/48", + "valid-lifetime": 4000 + } + ], + "valid-lifetime": 4000 + } + )"; + + ASSERT_NO_THROW(configure(config)); + + Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); + sol->setRemoteAddr(IOAddress("fe80::abcd")); + sol->setIface("eth0"); + sol->setIndex(ETH0_INDEX); + sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000)); + OptionPtr clientid = generateClientId(); + sol->addOption(clientid); + + // Pass it to the server and get an advertise + AllocEngine::ClientContext6 ctx; + bool drop = false; + srv_.initContext(sol, ctx, drop); + ASSERT_FALSE(drop); + Pkt6Ptr adv = srv_.processSolicit(ctx); + + // check if we get response at all + ASSERT_TRUE(adv); + + // We did not include any vendor opts in SOLICIT, so there should be none + // in ADVERTISE. + ASSERT_FALSE(adv->getOption(D6O_VENDOR_OPTS)); + + // Let's add a vendor-option (vendor-id=4491) with a single sub-option. + // That suboption has code 1 and is a docsis ORO option. + boost::shared_ptr<OptionUint16Array> vendor_oro(new OptionUint16Array(Option::V6, + DOCSIS3_V6_ORO)); + vendor_oro->addValue(DOCSIS3_V6_CONFIG_FILE); // Request option 33 + OptionPtr vendor(new OptionVendor(Option::V6, vendor_id)); + vendor->addOption(vendor_oro); + sol->addOption(vendor); + + // Need to process SOLICIT again after requesting new option. + AllocEngine::ClientContext6 ctx2; + srv_.initContext(sol, ctx2, drop); + ASSERT_FALSE(drop); + adv = srv_.processSolicit(ctx2); + ASSERT_TRUE(adv); + + // Check if there is (or not) a vendor option in the response. + OptionPtr tmp = adv->getOption(D6O_VENDOR_OPTS); + if (vendor_id != VENDOR_ID_CABLE_LABS) { + EXPECT_FALSE(tmp); + return; + } + ASSERT_TRUE(tmp); + + // The response should be OptionVendor object + boost::shared_ptr<OptionVendor> vendor_resp = + boost::dynamic_pointer_cast<OptionVendor>(tmp); + ASSERT_TRUE(vendor_resp); + + OptionPtr docsis33 = vendor_resp->getOption(33); + ASSERT_TRUE(docsis33); + + OptionStringPtr config_file = boost::dynamic_pointer_cast<OptionString>(docsis33); + ASSERT_TRUE(config_file); + EXPECT_EQ("normal_erouter_v6.cm", config_file->getValue()); + } + /// @brief Test what options a client can use to request vendor options. void testRequestingOfVendorOptions(vector<int8_t> const& client_options) { IfaceMgrTestConfig test_config(true); @@ -76,12 +183,12 @@ public: client.addExtraOption(vendor_option); } - // Let's check whether the server is not able to process this packet - // and include vivso with appropriate sub-options + // Let's check whether the server is able to process this packet + // and include the appropriate options. EXPECT_NO_THROW(client.doSolicit()); ASSERT_TRUE(client.getContext().response_); - // Check there's a response if an option was properly requested. + // Check that there is a response if an option was properly requested. // Otherwise check that a response has not been provided and stop here. OptionPtr response( client.getContext().response_->getOption(D6O_VENDOR_OPTS)); @@ -98,9 +205,9 @@ public: ASSERT_TRUE(response_vendor_options); EXPECT_EQ(vendor_id_, response_vendor_options->getVendorId()); - // Now check that it contains requested option with the appropriate - // content. - OptionPtr suboption(response_vendor_options->getOption(option_)); + // Check that it contains requested option with the appropriate content. + OptionPtr suboption( + response_vendor_options->getOption(option_)); ASSERT_TRUE(suboption); vector<uint8_t> binary_suboption = suboption->toBinary(false); string text(binary_suboption.begin(), binary_suboption.end()); @@ -235,93 +342,13 @@ TEST_F(VendorOptsTest, docsisVendorORO) { // This test checks if Option Request Option (ORO) in docsis (vendor-id=4491) // vendor options is parsed correctly and the requested options are actually assigned. TEST_F(VendorOptsTest, vendorOptionsORO) { + testVendorOptionsORO(VENDOR_ID_CABLE_LABS); +} - IfaceMgrTestConfig test_config(true); - - string config = "{ \"interfaces-config\": {" - " \"interfaces\": [ \"*\" ]" - "}," - "\"preferred-lifetime\": 3000," - "\"rebind-timer\": 2000, " - "\"renew-timer\": 1000, " - " \"option-def\": [ {" - " \"name\": \"config-file\"," - " \"code\": 33," - " \"type\": \"string\"," - " \"space\": \"vendor-4491\"" - " } ]," - " \"option-data\": [ {" - " \"name\": \"config-file\"," - " \"space\": \"vendor-4491\"," - " \"data\": \"normal_erouter_v6.cm\"" - " }]," - "\"subnet6\": [ { " - " \"pools\": [ { \"pool\": \"2001:db8:1::/64\" } ]," - " \"subnet\": \"2001:db8:1::/48\", " - " \"renew-timer\": 1000, " - " \"rebind-timer\": 1000, " - " \"preferred-lifetime\": 3000," - " \"valid-lifetime\": 4000," - " \"interface-id\": \"\"," - " \"interface\": \"eth0\"" - " } ]," - "\"valid-lifetime\": 4000 }"; - - ASSERT_NO_THROW(configure(config)); - - Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234)); - sol->setRemoteAddr(IOAddress("fe80::abcd")); - sol->setIface("eth0"); - sol->setIndex(ETH0_INDEX); - sol->addOption(generateIA(D6O_IA_NA, 234, 1500, 3000)); - OptionPtr clientid = generateClientId(); - sol->addOption(clientid); - - // Pass it to the server and get an advertise - AllocEngine::ClientContext6 ctx; - bool drop = false; - srv_.initContext(sol, ctx, drop); - ASSERT_FALSE(drop); - Pkt6Ptr adv = srv_.processSolicit(ctx); - - // check if we get response at all - ASSERT_TRUE(adv); - - // We did not include any vendor opts in SOLICIT, so there should be none - // in ADVERTISE. - ASSERT_FALSE(adv->getOption(D6O_VENDOR_OPTS)); - - // Let's add a vendor-option (vendor-id=4491) with a single sub-option. - // That suboption has code 1 and is a docsis ORO option. - boost::shared_ptr<OptionUint16Array> vendor_oro(new OptionUint16Array(Option::V6, - DOCSIS3_V6_ORO)); - vendor_oro->addValue(DOCSIS3_V6_CONFIG_FILE); // Request option 33 - OptionPtr vendor(new OptionVendor(Option::V6, 4491)); - vendor->addOption(vendor_oro); - sol->addOption(vendor); - - // Need to process SOLICIT again after requesting new option. - AllocEngine::ClientContext6 ctx2; - srv_.initContext(sol, ctx2, drop); - ASSERT_FALSE(drop); - adv = srv_.processSolicit(ctx2); - ASSERT_TRUE(adv); - - // Check if there is vendor option response - OptionPtr tmp = adv->getOption(D6O_VENDOR_OPTS); - ASSERT_TRUE(tmp); - - // The response should be OptionVendor object - boost::shared_ptr<OptionVendor> vendor_resp = - boost::dynamic_pointer_cast<OptionVendor>(tmp); - ASSERT_TRUE(vendor_resp); - - OptionPtr docsis33 = vendor_resp->getOption(33); - ASSERT_TRUE(docsis33); - - OptionStringPtr config_file = boost::dynamic_pointer_cast<OptionString>(docsis33); - ASSERT_TRUE(config_file); - EXPECT_EQ("normal_erouter_v6.cm", config_file->getValue()); +// Same as vendorOptionsORO except a different vendor ID than Cable Labs is +// provided and vendor options are expected to not be present in the response. +TEST_F(VendorOptsTest, vendorOptionsORODifferentVendorID) { + testVendorOptionsORO(32768); } // This test checks if Option Request Option (ORO) in docsis (vendor-id=4491) |