]> git.ipfire.org Git - thirdparty/kea.git/commitdiff
[#1405] out-of-pool is also in-subnet
authorRazvan Becheriu <razvan@isc.org>
Wed, 28 Oct 2020 08:06:24 +0000 (10:06 +0200)
committerRazvan Becheriu <razvan@isc.org>
Wed, 18 Nov 2020 13:55:23 +0000 (15:55 +0200)
src/bin/dhcp4/dhcp4_messages.mes
src/bin/dhcp4/json_config_parser.cc
src/bin/dhcp6/dhcp6_messages.mes
src/bin/dhcp6/json_config_parser.cc
src/lib/dhcpsrv/alloc_engine.cc
src/lib/dhcpsrv/network.cc
src/lib/dhcpsrv/parsers/reservation_modes_parser.cc

index cb1c4d33d8899e0633da626728f8846e9f11bae3..1c4b7785ffdb3a2aeb451fa5957cf3e665eead9e 100644 (file)
@@ -274,6 +274,9 @@ A debug message issued when deferred unpacking of an option failed, making it
 to be left unpacked in the packet. The first argument is the option code,
 the second the error.
 
+% DHCP4_DEPRECATED_RESERVATION_MODE deprecated reservation-mode parameter; use reservations-global, reservations-in-subnet and reservations-out-of-pool instead.
+A warning message indicating that reservation-mode parameter is deprecated.
+
 % DHCP4_DEVELOPMENT_VERSION This software is a development branch of Kea. It is not recommended for production use.
 This warning message is displayed when the version is a development
 (vs stable) one: the second number of the version is odd.
index 199b06c301e00f0fb770db67740034b3f840705a..95a586705b58f959964abb4651559497534d266b 100644 (file)
@@ -376,7 +376,7 @@ configureDhcp4Server(Dhcpv4Srv& server, isc::data::ConstElementPtr config_set,
         }
         ConstElementPtr reservation_mode = mutable_cfg->get("reservation-mode");
         if (reservation_mode) {
-            // log warning for deprecated option
+            LOG_WARN(dhcp4_logger, DHCP4_DEPRECATED_RESERVATION_MODE);
             if (found) {
                 isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
                                            " and one of 'reservations-out-of-pool'"
index e275ae5da98a78451812ae961ea05b175f7da56b..2dd4dfb2f8ead09611d745f1c7e38fa6751d4f53 100644 (file)
@@ -288,6 +288,9 @@ received in Decline message. It's expected that the option will contain an
 address that is being declined. Specific information will be printed in a
 separate message.
 
+% DHCP6_DEPRECATED_RESERVATION_MODE deprecated reservation-mode parameter; use reservations-global, reservations-in-subnet and reservations-out-of-pool instead.
+A warning message indicating that reservation-mode parameter is deprecated.
+
 % DHCP6_DEVELOPMENT_VERSION This software is a development branch of Kea. It is not recommended for production use.
 This warning message is displayed when the version is a development
 (vs stable) one: the second number of the version is odd.
index 6af3c0c3ca3feb8b8aa204a6e4402e769497a825..c38447dd8a36e92d8e25e61b1f93506cb7d0b22f 100644 (file)
@@ -477,7 +477,7 @@ configureDhcp6Server(Dhcpv6Srv& server, isc::data::ConstElementPtr config_set,
         }
         ConstElementPtr reservation_mode = mutable_cfg->get("reservation-mode");
         if (reservation_mode) {
-            // log warning for deprecated option
+            LOG_WARN(dhcp6_logger, DHCP6_DEPRECATED_RESERVATION_MODE);
             if (found) {
                 isc_throw(DhcpConfigError, "invalid use of both 'reservation-mode'"
                                            " and one of 'reservations-out-of-pool'"
index 2d91186cc1b13f76ec9b9dcc3d423a4c885859b5..6e20d4a1c0fa4e3c8914f493f96ef8ba54bf8499 100644 (file)
@@ -1074,7 +1074,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
             }
 
             // First check for reservation when it is the choice.
-            if (check_reservation_first && (hr_mode & Network::HR_IN_SUBNET)) {
+            if (check_reservation_first && ((hr_mode & Network::HR_IN_SUBNET) &&
+                !(hr_mode & Network::HR_OUT_OF_POOL))) {
                 auto hosts = getIPv6Resrv(subnet->getID(), candidate);
                 if (!hosts.empty()) {
                     // Don't allocate.
@@ -1099,7 +1100,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
                 /// In-pool reservations: Check if this address is reserved for someone
                 /// else. There is no need to check for whom it is reserved, because if
                 /// it has been reserved for us we would have already allocated a lease.
-                if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET)) {
+                if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET) &&
+                    !(hr_mode & Network::HR_OUT_OF_POOL)) {
                     auto hosts = getIPv6Resrv(subnet->getID(), candidate);
                     if (!hosts.empty()) {
                         // Don't allocate.
@@ -1131,7 +1133,8 @@ AllocEngine::allocateUnreservedLeases6(ClientContext6& ctx) {
                 // allocation attempts.
             } else if (existing->expired()) {
                 // Make sure it's not reserved.
-                if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET)) {
+                if (!check_reservation_first && (hr_mode & Network::HR_IN_SUBNET) &&
+                    !(hr_mode & Network::HR_OUT_OF_POOL)) {
                     auto hosts = getIPv6Resrv(subnet->getID(), candidate);
                     if (!hosts.empty()) {
                         // Don't allocate.
@@ -2951,10 +2954,10 @@ namespace {
 /// @return true if the address is reserved for another client.
 bool
 addressReserved(const IOAddress& address, const AllocEngine::ClientContext4& ctx) {
-    if (ctx.subnet_ &&
-        ((ctx.subnet_->getHostReservationMode() & Network::HR_IN_SUBNET) ||
-         ((ctx.subnet_->getHostReservationMode() & Network::HR_OUT_OF_POOL) &&
-          (!ctx.subnet_->inPool(Lease::TYPE_V4, address))))) {
+    bool in_subnet = (ctx.subnet_->getHostReservationMode() & Network::HR_IN_SUBNET);
+    bool out_of_pool = (ctx.subnet_->getHostReservationMode() & Network::HR_OUT_OF_POOL);
+    if (ctx.subnet_ && ((in_subnet && !out_of_pool) ||
+        (out_of_pool && (!ctx.subnet_->inPool(Lease::TYPE_V4, address))))) {
         // The global parameter ip-reservations-unique controls whether it is allowed
         // to specify multiple reservations for the same IP address or delegated prefix
         // or IP reservations must be unique. Some host backends do not support the
@@ -3032,11 +3035,12 @@ hasAddressReservation(AllocEngine::ClientContext4& ctx) {
         }
 
         auto host = ctx.hosts_.find(subnet->getID());
-        if ((host != ctx.hosts_.end()) &&
-            !(host->second->getIPv4Reservation().isV4Zero()) &&
-            ((subnet->getHostReservationMode() & Network::HR_IN_SUBNET) ||
-             ((subnet->getHostReservationMode() & Network::HR_OUT_OF_POOL) &&
-              (!subnet->inPool(Lease::TYPE_V4, host->second->getIPv4Reservation()))))) {
+        bool in_subnet = (subnet->getHostReservationMode() & Network::HR_IN_SUBNET);
+        bool out_of_pool = (subnet->getHostReservationMode() & Network::HR_OUT_OF_POOL);
+        auto reservation = host->second->getIPv4Reservation();
+        if ((host != ctx.hosts_.end()) && !reservation.isV4Zero() &&
+            ((in_subnet && !out_of_pool) ||
+             (out_of_pool && !subnet->inPool(Lease::TYPE_V4, reservation)))) {
             ctx.subnet_ = subnet;
             return (true);
         }
index 26e27e3c3572e05ad7e6613e61193b9442458eae..08e65f673af3e0273d59cca57f232ec1989ce245 100644 (file)
@@ -111,7 +111,7 @@ Network::hrModeFromString(const std::string& hr_mode_name) {
          (hr_mode_name.compare("off") == 0) )  {
         return (Network::HR_DISABLED);
     } else if (hr_mode_name.compare("out-of-pool") == 0) {
-        return (Network::HR_OUT_OF_POOL);
+        return (Network::HR_OUT_OF_POOL|Network::HR_IN_SUBNET);
     } else if (hr_mode_name.compare("global") == 0) {
         return (Network::HR_GLOBAL);
     } else if (hr_mode_name.compare("all") == 0) {
index fcde1bbfa683a5cbe982806252583f56f98956dc..fecb0757da66dd467193c6366aa1b889f9907227 100644 (file)
@@ -27,13 +27,15 @@ HostReservationModesParser::parse(const ConstElementPtr& config_elem) {
 
     ConstElementPtr elem;
     uint8_t flags = 0;
+    bool force_true = false;
 
     try {
-        elem  = config_elem->get("reservations-global");
+        elem  = config_elem->get("reservations-out-of-pool");
         if (elem) {
             bool value = elem->boolValue();
             if (value) {
-                flags |= Network::HR_GLOBAL;
+                flags |= Network::HR_IN_SUBNET | Network::HR_OUT_OF_POOL;
+                force_true = true;
             }
         }
 
@@ -42,14 +44,17 @@ HostReservationModesParser::parse(const ConstElementPtr& config_elem) {
             bool value = elem->boolValue();
             if (value) {
                 flags |= Network::HR_IN_SUBNET;
+            } else if (force_true) {
+                isc_throw(DhcpConfigError, "invalid use of disabled 'reservations-in-subnet'"
+                                           " when enabled 'reservations-out-of-pool'");
             }
         }
 
-        elem  = config_elem->get("reservations-out-of-pool");
+        elem  = config_elem->get("reservations-global");
         if (elem) {
             bool value = elem->boolValue();
             if (value) {
-                flags |= Network::HR_IN_SUBNET | Network::HR_OUT_OF_POOL;
+                flags |= Network::HR_GLOBAL;
             }
         }
     } catch (const Exception& ex) {