]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[4308] Implemented subnet selection based on interface name.
authorTomek Mrugalski <tomasz@isc.org>
Wed, 18 May 2016 15:38:15 +0000 (17:38 +0200)
committerTomek Mrugalski <tomasz@isc.org>
Thu, 19 May 2016 12:10:57 +0000 (14:10 +0200)
src/lib/dhcpsrv/cfg_subnets4.cc
src/lib/dhcpsrv/cfg_subnets4.h

index 837d87e6ee61eb77c4858adc15b477999b86eaee..35a246981f8f9dfccf1b5cd7e60eef4f60e1407d 100644 (file)
@@ -138,7 +138,16 @@ CfgSubnets4::selectSubnet(const SubnetSelector& selector) const {
                       << " doesn't exist and therefore it is impossible"
                       " to find a suitable subnet for its IPv4 address");
         }
-        iface->getAddress4(address);
+
+        // Attempt to select subnet based on the interface name.
+        Subnet4Ptr subnet = selectSubnet(selector.iface_name_,
+                                         selector.client_classes_);
+
+        // If it matches - great. If not, we'll try to use a different
+        // selection criteria below.
+        if (subnet) {
+            return (subnet);
+        }
     }
 
     // Unable to find a suitable address to use for subnet selection.
@@ -151,6 +160,34 @@ CfgSubnets4::selectSubnet(const SubnetSelector& selector) const {
     return (selectSubnet(address, selector.client_classes_));
 }
 
+Subnet4Ptr
+CfgSubnets4::selectSubnet(const std::string& iface,
+                 const ClientClasses& client_classes) const {
+    for (Subnet4Collection::const_iterator subnet = subnets_.begin();
+         subnet != subnets_.end(); ++subnet) {
+
+        // If there's no interface specified for this subnet, proceed to
+        // the next subnet.
+        if ((*subnet)->getIface().empty()) {
+            continue;
+        }
+
+        // If it's specified, but does not match, proceed to the next
+        // subnet.
+        if ((*subnet)->getIface() != iface) {
+            continue;
+        }
+
+        // Eliminate those subnets that do not meet client class criteria.
+        if ((*subnet)->clientSupported(client_classes)) {
+            return (*subnet);
+        }
+    }
+
+    // Failed to find a subnet.
+    return (Subnet4Ptr());
+}
+
 Subnet4Ptr
 CfgSubnets4::selectSubnet(const IOAddress& address,
                  const ClientClasses& client_classes) const {
@@ -172,6 +209,7 @@ CfgSubnets4::selectSubnet(const IOAddress& address,
     return (Subnet4Ptr());
 }
 
+
 bool
 CfgSubnets4::isDuplicate(const Subnet4& subnet) const {
     for (Subnet4Collection::const_iterator subnet_it = subnets_.begin();
index 6ff0a73e18a0c26ce31bac56111e511f18800e9e..8e9b7fa38963bca61c0207d5f47c334ffef70d54 100644 (file)
@@ -120,6 +120,30 @@ public:
                             const ClientClasses& client_classes
                             = ClientClasses()) const;
 
+    /// @brief Returns pointer to a subnet if provided interface name matches.
+    ///
+    /// This method returns a pointer to the subnet if the interface name passed
+    /// in parameter matches that of a subnet. This is mainly used for matching
+    /// local incoming traffic, even when the addresses on local interfaces do
+    /// not match subnet definition. This method is also called by the
+    /// @c selectSubnet(SubnetSelector).
+    ///
+    /// @todo This method requires performance improvement! It currently
+    /// iterates over all existing subnets to find the one which fulfils
+    /// the search criteria. The subnet storage is implemented as a simple
+    /// STL vector which precludes fast searches using specific keys.
+    /// Hence, full scan is required. To improve the search performance a
+    /// different container type is required, e.g. multi-index container,
+    /// or something of a similar functionality.
+    ///
+    /// @param iface name of the interface to be matched.
+    /// @param client_classes Optional parameter specifying the classes that
+    /// the client belongs to.
+    ///
+    /// @return Pointer to the selected subnet or NULL if no subnet found.
+    Subnet4Ptr selectSubnet(const std::string& iface,
+                            const ClientClasses& client_classes) const;
+
     /// @brief Attempts to do subnet selection based on DHCP4o6 information
     ///
     /// The algorithm implemented is as follows: