Parcourir la source

[5016] Update server code and tests to properly use exclude option.

Marcin Siodelski il y a 8 ans
Parent
commit
3e7fa856b7

+ 21 - 23
src/bin/dhcp6/dhcp6_srv.cc

@@ -893,26 +893,7 @@ Dhcpv6Srv::appendRequestedOptions(const Pkt6Ptr& question, Pkt6Ptr& answer,
     // Get the list of options that client requested.
     const std::vector<uint16_t>& requested_opts = option_oro->getValues();
 
-    if (co_list.empty()) {
-        // If there are no options configured, we at least have to check if
-        // the client has requested PD exclude, which is configured as
-        // part of the pool configuration.
-        ctx.pd_exclude_requested_ = (std::find(requested_opts.begin(),
-                                               requested_opts.end(),
-                                               D6O_PD_EXCLUDE) !=
-                                     requested_opts.end());
-        return;
-    }
-
     BOOST_FOREACH(uint16_t opt, requested_opts) {
-        // Prefix Exclude option requires special handling, as it can
-        // be configured as part of the pool configuration.
-        if (opt == D6O_PD_EXCLUDE) {
-            ctx.pd_exclude_requested_ = true;
-            // Prefix Exclude can only be included in the IA Prefix option
-            // of IA_PD. Thus there is nothing more to do here.
-            continue;
-        }
         // Iterate on the configured option list
         for (CfgOptionList::const_iterator copts = co_list.begin();
              copts != co_list.end(); ++copts) {
@@ -1576,6 +1557,8 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
         ia_rsp->setT1(subnet->getT1());
         ia_rsp->setT2(subnet->getT2());
 
+        const bool pd_exclude_requested = requestedInORO(query, D6O_PD_EXCLUDE);
+
         for (Lease6Collection::iterator l = leases.begin();
              l != leases.end(); ++l) {
 
@@ -1594,14 +1577,12 @@ Dhcpv6Srv::assignIA_PD(const Pkt6Ptr& query, const Pkt6Ptr& answer,
                                          (*l)->valid_lft_));
             ia_rsp->addOption(addr);
 
-            if (ctx.pd_exclude_requested_) {
+            if (pd_exclude_requested) {
                 // PD exclude option has been requested via ORO, thus we need to
                 // include it if the pool configuration specifies this option.
                 Pool6Ptr pool = boost::dynamic_pointer_cast<
                     Pool6>(subnet->getPool(Lease::TYPE_PD, (*l)->addr_));
                 if (pool && pool->getExcludedPrefixLength() > 0) {
-                    std::cout << pool->getExcludedPrefix() << "/"
-                        << (unsigned)pool->getExcludedPrefixLength() << std::endl;
                     OptionPtr opt(new Option6PDExclude((*l)->addr_,
                                                        (*l)->prefixlen_,
                                                        pool->getExcludedPrefix(),
@@ -1877,6 +1858,8 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
     // into temporary container.
     AllocEngine::HintContainer hints = ctx.currentIA().hints_;
 
+    const bool pd_exclude_requested = requestedInORO(query, D6O_PD_EXCLUDE);
+
     // For all the leases we have now, add the IAPPREFIX with non-zero lifetimes
     for (Lease6Collection::const_iterator l = leases.begin(); l != leases.end(); ++l) {
 
@@ -1885,7 +1868,8 @@ Dhcpv6Srv::extendIA_PD(const Pkt6Ptr& query,
                                (*l)->preferred_lft_, (*l)->valid_lft_));
         ia_rsp->addOption(prf);
 
-        if (ctx.pd_exclude_requested_) {
+
+        if (pd_exclude_requested) {
             // PD exclude option has been requested via ORO, thus we need to
             // include it if the pool configuration specifies this option.
             Pool6Ptr pool = boost::dynamic_pointer_cast<
@@ -3288,5 +3272,19 @@ int Dhcpv6Srv::getHookIndexBuffer6Send() {
     return (Hooks.hook_index_buffer6_send_);
 }
 
+bool
+Dhcpv6Srv::requestedInORO(const Pkt6Ptr& query, const uint16_t code) const {
+    OptionUint16ArrayPtr oro =
+        boost::dynamic_pointer_cast<OptionUint16Array>(query->getOption(D6O_ORO));
+
+    if (oro) {
+        const std::vector<uint16_t>& codes = oro->getValues();
+        return (std::find(codes.begin(), codes.end(), code) != codes.end());
+    }
+
+    return (false);
+}
+
+
 };
 };

+ 9 - 0
src/bin/dhcp6/dhcp6_srv.h

@@ -805,6 +805,15 @@ private:
     /// @param query packet received
     static void processStatsReceived(const Pkt6Ptr& query);
 
+    /// @brief Checks if the specified option code has been requested using
+    /// the Option Request option.
+    ///
+    /// @param query Pointer to the client's query.
+    /// @parma code Option code.
+    ///
+    /// @return true if option has been requested in the ORO.
+    bool requestedInORO(const Pkt6Ptr& query, const uint16_t code) const;
+
     /// UDP port number on which server listens.
     uint16_t port_;
 

+ 2 - 2
src/bin/dhcp6/tests/renew_unittest.cc

@@ -218,7 +218,7 @@ const char* RENEW_CONFIGS[] = {
         "    \"interface-id\": \"\","
         "    \"interface\": \"eth0\""
         " } ],"
-        "\"valid-lifetime\": 4000 }
+        "\"valid-lifetime\": 4000 }"
 };
 
 /// @brief Test fixture class for testing Renew.
@@ -352,7 +352,7 @@ TEST_F(RenewTest, renewWithExcludedPrefix) {
     ASSERT_FALSE(option);
 
     // Reconfigure the server to use the prefix pool with excluded prefix.
-    configure(RENEW_CONFIGS[4], *client.getServer());
+    configure(RENEW_CONFIGS[5], *client.getServer());
 
     // Send Renew message to the server, including IA_NA and IA_PD.
     ASSERT_NO_THROW(client.doRenew());

+ 1 - 1
src/bin/dhcp6/tests/sarr_unittest.cc

@@ -339,7 +339,7 @@ TEST_F(SARRTest, directClientExcludedPrefix) {
     // Configure client to request IA_PD.
     client.requestPrefix();
     client.requestOption(D6O_PD_EXCLUDE);
-    configure(CONFIGS[2], *client.getServer());
+    configure(CONFIGS[3], *client.getServer());
     // Make sure we ended-up having expected number of subnets configured.
     const Subnet6Collection* subnets = CfgMgr::instance().getCurrentCfg()->
         getCfgSubnets6()->getAll();

+ 1 - 1
src/lib/dhcpsrv/alloc_engine.cc

@@ -350,7 +350,7 @@ AllocEngine::ClientContext6::ClientContext6(const Subnet6Ptr& subnet,
       duid_(duid), hwaddr_(), host_identifiers_(), host_(),
       fwd_dns_update_(fwd_dns), rev_dns_update_(rev_dns),
       hostname_(hostname), callout_handle_(callout_handle),
-      allocated_resources_(), ias_(), pd_exclude_requested_(false) {
+      allocated_resources_(), ias_() {
 
     // Initialize host identifiers.
     if (duid) {

+ 0 - 4
src/lib/dhcpsrv/alloc_engine.h

@@ -397,10 +397,6 @@ public:
         /// @brief Container holding IA specific contexts.
         std::vector<IAContext> ias_;
 
-        /// @brief Indicates if PD exclude option has been requested by a
-        /// client.
-        bool pd_exclude_requested_;
-
         /// @brief Convenience method adding allocated prefix or address.
         ///
         /// @param prefix Prefix or address.

+ 1 - 1
src/lib/dhcpsrv/dhcp4o6_ipc.cc

@@ -71,7 +71,7 @@ int Dhcp4o6IpcBase::open(uint16_t port, EndpointType endpoint_type) {
     }
     // We'll connect to the loopback address so bind to it too.
     local6.sin6_addr.s6_addr[15] = 1;
-    if (bind(sock, (struct sockaddr *)&local6, sizeof(local6)) < 0) {
+    if (::bind(sock, (struct sockaddr *)&local6, sizeof(local6)) < 0) {
         ::close(sock);
         isc_throw(Dhcp4o6IpcError, "Failed to bind DHCP4o6 socket.");
     }

+ 1 - 5
src/lib/dhcpsrv/pgsql_host_data_source.cc

@@ -525,11 +525,7 @@ private:
             // If the option space is a standard DHCPv4 or DHCPv6 option space,
             // this is most likely a standard option, for which we have a
             // definition created within libdhcp++.
-            OptionDefinitionPtr def;
-            if ((space == DHCP4_OPTION_SPACE) ||
-                (space == DHCP6_OPTION_SPACE)) {
-                def = LibDHCP::getOptionDef(universe_, code);
-            }
+            OptionDefinitionPtr def = LibDHCP::getOptionDef(space, code);
 
             // Otherwise, we may check if this an option encapsulated within the
             // vendor space.