Browse Source

[4097a] Changed classSpecificProcessing to be applied only to requested options

Francis Dupont 9 years ago
parent
commit
4b644a946c
2 changed files with 45 additions and 16 deletions
  1. 23 14
      src/bin/dhcp4/dhcp4_srv.cc
  2. 22 2
      src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

+ 23 - 14
src/bin/dhcp4/dhcp4_srv.cc

@@ -2374,6 +2374,18 @@ Dhcpv4Srv::classSpecificProcessing(const Dhcpv4Exchange& ex) {
         rsp->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS());
     }
 
+    // try to get the 'Parameter Request List' option which holds the
+    // codes of requested options.
+    OptionUint8ArrayPtr option_prl = boost::dynamic_pointer_cast<
+        OptionUint8Array>(query->getOption(DHO_DHCP_PARAMETER_REQUEST_LIST));
+    // If there is no PRL option in the message from the client then
+    // there is nothing to do.
+    if (!option_prl) {
+        return (true);
+    }
+    // Get the codes of requested options.
+    const std::vector<uint8_t>& requested_opts = option_prl->getValues();
+
     // Process each class in the packet
     const ClientClasses& classes = query->getClasses();
     for (ClientClasses::const_iterator cclass = classes.begin();
@@ -2385,20 +2397,17 @@ Dhcpv4Srv::classSpecificProcessing(const Dhcpv4Exchange& ex) {
             // Not found
             continue;
         }
-        // Get the configured options of this class
-        const OptionContainerPtr& options = ccdef->getCfgOption()->getAll("dhcp4");
-        if (!options || options->empty()) {
-            continue;
-        }
-        // Go through each OptionDescriptor
-        for (OptionContainer::const_iterator desc = options->begin();
-             desc != options->end(); ++desc) {
-            OptionPtr opt = desc->option_;
-            // Add the option if it doesn't exist yet
-            if (!rsp->getOption(opt->getType())) {
-                rsp->addOption(opt);
-            }
-        }
+	// For each requested option code get the instance of the option
+	// in the class to be returned to the client.
+	for (std::vector<uint8_t>::const_iterator opt = requested_opts.begin();
+	     opt != requested_opts.end(); ++opt) {
+	    if (!rsp->getOption(*opt)) {
+		OptionDescriptor desc = ccdef->getCfgOption()->get("dhcp4", *opt);
+		if (desc.option_) {
+		    rsp->addOption(desc.option_);
+		}
+	    }
+	}
     }
 
     return (true);

+ 22 - 2
src/bin/dhcp4/tests/dhcp4_srv_unittest.cc

@@ -1711,24 +1711,39 @@ TEST_F(Dhcpv4SrvTest, matchClassification) {
     query1->setRemoteAddr(IOAddress("192.0.2.1"));
     Pkt4Ptr query2(new Pkt4(DHCPDISCOVER, 1234));
     query2->setRemoteAddr(IOAddress("192.0.2.1"));
+    Pkt4Ptr query3(new Pkt4(DHCPDISCOVER, 1234));
+    query3->setRemoteAddr(IOAddress("192.0.2.1"));
 
-    // Create and add a host-name option to the first query
+    // Create and add a PRL option to the first 2 queries
+    OptionUint8ArrayPtr prl(new OptionUint8Array(Option::V4,
+                                                 DHO_DHCP_PARAMETER_REQUEST_LIST));
+    ASSERT_TRUE(prl);
+    prl->addValue(DHO_IP_FORWARDING);
+    query1->addOption(prl);
+    query2->addOption(prl);
+
+    // Create and add a host-name option to the first and last queries
     OptionStringPtr hostname(new OptionString(Option::V4, 12, "foo"));
     ASSERT_TRUE(hostname);
     query1->addOption(hostname);
+    query3->addOption(hostname);
 
     // Classify packets
     srv.classifyPacket(query1);
     srv.classifyPacket(query2);
+    srv.classifyPacket(query3);
 
-    // The first packet (and only the first) should be in the router class
+    // Packets at the exception of the second should be in the router class
     EXPECT_TRUE(query1->inClass("router"));
     EXPECT_FALSE(query2->inClass("router"));
+    EXPECT_TRUE(query3->inClass("router"));
 
     Dhcpv4Exchange ex1 = createExchange(query1);
     Pkt4Ptr response1 = ex1.getResponse();
     Dhcpv4Exchange ex2 = createExchange(query2);
     Pkt4Ptr response2 = ex2.getResponse();
+    Dhcpv4Exchange ex3 = createExchange(query3);
+    Pkt4Ptr response3 = ex3.getResponse();
 
     // Classification processing should add an ip-forwarding option
     srv.classSpecificProcessing(ex1);
@@ -1739,6 +1754,11 @@ TEST_F(Dhcpv4SrvTest, matchClassification) {
     srv.classSpecificProcessing(ex2);
     OptionPtr opt2 = response2->getOption(DHO_IP_FORWARDING);
     EXPECT_FALSE(opt2);
+
+    // But only for the first exchange
+    srv.classSpecificProcessing(ex3);
+    OptionPtr opt3 = response3->getOption(DHO_IP_FORWARDING);
+    EXPECT_FALSE(opt3);
 }
 
 // Checks subnet options have the priority over class options