From 4b644a946c84eaaf783bde980f40866db6072274 Mon Sep 17 00:00:00 2001 From: Francis Dupont Date: Sat, 21 Nov 2015 09:23:24 +0100 Subject: [PATCH] [4097a] Changed classSpecificProcessing to be applied only to requested options --- src/bin/dhcp4/dhcp4_srv.cc | 37 ++++++++++++++--------- src/bin/dhcp4/tests/dhcp4_srv_unittest.cc | 24 +++++++++++++-- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/bin/dhcp4/dhcp4_srv.cc b/src/bin/dhcp4/dhcp4_srv.cc index 322ad01e29..5be11b2c4d 100644 --- a/src/bin/dhcp4/dhcp4_srv.cc +++ b/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& 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::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); diff --git a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc b/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc index 6a2d5e7701..0a772d262d 100644 --- a/src/bin/dhcp4/tests/dhcp4_srv_unittest.cc +++ b/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 -- 2.47.2