|
@@ -1451,6 +1451,89 @@ TEST_F(Dhcpv4SrvTest, vendorOptionsORO) {
|
|
|
EXPECT_EQ("192.0.2.2", addrs[1].toText());
|
|
|
}
|
|
|
|
|
|
+// This test checks if Option Request Option (ORO) in docsis (vendor-id=4491)
|
|
|
+// vendor options is parsed correctly and persistent options are actually assigned.
|
|
|
+TEST_F(Dhcpv4SrvTest, vendorPersistentOptions) {
|
|
|
+ IfaceMgrTestConfig test_config(true);
|
|
|
+ IfaceMgr::instance().openSockets4();
|
|
|
+
|
|
|
+ NakedDhcpv4Srv srv(0);
|
|
|
+
|
|
|
+ ConstElementPtr x;
|
|
|
+ string config = "{ \"interfaces-config\": {"
|
|
|
+ " \"interfaces\": [ \"*\" ]"
|
|
|
+ "},"
|
|
|
+ "\"rebind-timer\": 2000, "
|
|
|
+ "\"renew-timer\": 1000, "
|
|
|
+ " \"option-data\": [ {"
|
|
|
+ " \"name\": \"tftp-servers\","
|
|
|
+ " \"space\": \"vendor-4491\","
|
|
|
+ " \"code\": 2,"
|
|
|
+ " \"data\": \"192.0.2.1, 192.0.2.2\","
|
|
|
+ " \"csv-format\": true,"
|
|
|
+ " \"persistent\": true"
|
|
|
+ " }],"
|
|
|
+ "\"subnet4\": [ { "
|
|
|
+ " \"pools\": [ { \"pool\": \"192.0.2.0/25\" } ],"
|
|
|
+ " \"subnet\": \"192.0.2.0/24\", "
|
|
|
+ " \"rebind-timer\": 2000, "
|
|
|
+ " \"renew-timer\": 1000, "
|
|
|
+ " \"valid-lifetime\": 4000,"
|
|
|
+ " \"interface\": \"eth0\" "
|
|
|
+ " } ],"
|
|
|
+ "\"valid-lifetime\": 4000 }";
|
|
|
+
|
|
|
+ ConstElementPtr json;
|
|
|
+ ASSERT_NO_THROW(json = parseDHCP4(config));
|
|
|
+
|
|
|
+ EXPECT_NO_THROW(x = configureDhcp4Server(srv, json));
|
|
|
+ ASSERT_TRUE(x);
|
|
|
+ comment_ = isc::config::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");
|
|
|
+
|
|
|
+ // Let's add a vendor-option (vendor-id=4491).
|
|
|
+ OptionPtr vendor(new OptionVendor(Option::V4, 4491));
|
|
|
+ dis->addOption(vendor);
|
|
|
+
|
|
|
+ // Pass it to the server and get an advertise
|
|
|
+ Pkt4Ptr offer = srv.processDiscover(dis);
|
|
|
+
|
|
|
+ // check if we get response at all
|
|
|
+ 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);
|
|
|
+
|
|
|
+ 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());
|
|
|
+}
|
|
|
+
|
|
|
// Test checks whether it is possible to use option definitions defined in
|
|
|
// src/lib/dhcp/docsis3_option_defs.h.
|
|
|
TEST_F(Dhcpv4SrvTest, vendorOptionsDocsisDefinitions) {
|
|
@@ -1952,6 +2035,85 @@ TEST_F(Dhcpv4SrvTest, classGlobalPriority) {
|
|
|
EXPECT_NE(0, opt->getUint8());
|
|
|
}
|
|
|
|
|
|
+// Checks class options have the priority over global persistent options
|
|
|
+TEST_F(Dhcpv4SrvTest, classGlobalPersistency) {
|
|
|
+ IfaceMgrTestConfig test_config(true);
|
|
|
+ IfaceMgr::instance().openSockets4();
|
|
|
+
|
|
|
+ NakedDhcpv4Srv srv(0);
|
|
|
+
|
|
|
+ // A global ip-forwarding option is set in the response.
|
|
|
+ // The router class matches incoming packets with foo in a host-name
|
|
|
+ // option (code 12) and sets an ip-forwarding option in the response.
|
|
|
+ // Note the persistency flag follows a "OR" semantic so to set
|
|
|
+ // it to false (or to leave the default) has no effect.
|
|
|
+ string config = "{ \"interfaces-config\": {"
|
|
|
+ " \"interfaces\": [ \"*\" ] }, "
|
|
|
+ "\"rebind-timer\": 2000, "
|
|
|
+ "\"renew-timer\": 1000, "
|
|
|
+ "\"valid-lifetime\": 4000, "
|
|
|
+ "\"subnet4\": [ "
|
|
|
+ "{ \"pools\": [ { \"pool\": \"192.0.2.1 - 192.0.2.100\" } ], "
|
|
|
+ " \"subnet\": \"192.0.2.0/24\" } ], "
|
|
|
+ "\"option-data\": ["
|
|
|
+ " { \"name\": \"ip-forwarding\", "
|
|
|
+ " \"data\": \"false\", "
|
|
|
+ " \"persistent\": true } ], "
|
|
|
+ "\"client-classes\": [ "
|
|
|
+ "{ \"name\": \"router\","
|
|
|
+ " \"option-data\": ["
|
|
|
+ " { \"name\": \"ip-forwarding\", "
|
|
|
+ " \"data\": \"true\", "
|
|
|
+ " \"persistent\": false } ], "
|
|
|
+ " \"test\": \"option[12].text == 'foo'\" } ] }";
|
|
|
+
|
|
|
+ ConstElementPtr json;
|
|
|
+ ASSERT_NO_THROW(json = parseDHCP4(config));
|
|
|
+ ConstElementPtr status;
|
|
|
+
|
|
|
+ // Configure the server and make sure the config is accepted
|
|
|
+ EXPECT_NO_THROW(status = configureDhcp4Server(srv, json));
|
|
|
+ ASSERT_TRUE(status);
|
|
|
+ comment_ = config::parseAnswer(rcode_, status);
|
|
|
+ ASSERT_EQ(0, rcode_);
|
|
|
+
|
|
|
+ CfgMgr::instance().commit();
|
|
|
+
|
|
|
+ // Create a packet with enough to select the subnet and go through
|
|
|
+ // the DISCOVER processing
|
|
|
+ Pkt4Ptr query(new Pkt4(DHCPDISCOVER, 1234));
|
|
|
+ query->setRemoteAddr(IOAddress("192.0.2.1"));
|
|
|
+ OptionPtr clientid = generateClientId();
|
|
|
+ query->addOption(clientid);
|
|
|
+ query->setIface("eth1");
|
|
|
+
|
|
|
+ // Do not add a PRL
|
|
|
+ OptionPtr prl = query->getOption(DHO_DHCP_PARAMETER_REQUEST_LIST);
|
|
|
+ EXPECT_FALSE(prl);
|
|
|
+
|
|
|
+ // Create and add a host-name option to the query
|
|
|
+ OptionStringPtr hostname(new OptionString(Option::V4, 12, "foo"));
|
|
|
+ ASSERT_TRUE(hostname);
|
|
|
+ query->addOption(hostname);
|
|
|
+
|
|
|
+ // Classify the packet
|
|
|
+ srv.classifyPacket(query);
|
|
|
+
|
|
|
+ // The packet should be in the router class
|
|
|
+ EXPECT_TRUE(query->inClass("router"));
|
|
|
+
|
|
|
+ // Process the query
|
|
|
+ Pkt4Ptr response = srv.processDiscover(query);
|
|
|
+
|
|
|
+ // Processing should add an ip-forwarding option
|
|
|
+ OptionPtr opt = response->getOption(DHO_IP_FORWARDING);
|
|
|
+ ASSERT_TRUE(opt);
|
|
|
+ ASSERT_GT(opt->len(), opt->getHeaderLen());
|
|
|
+ // Classification sets the value to true/1, global to false/0
|
|
|
+ // Here class has the priority
|
|
|
+ EXPECT_NE(0, opt->getUint8());
|
|
|
+}
|
|
|
+
|
|
|
// Checks if the client-class field is indeed used for subnet selection.
|
|
|
// Note that packet classification is already checked in Dhcpv4SrvTest
|
|
|
// .*Classification above.
|