From: Razvan Becheriu Date: Wed, 28 Oct 2020 08:06:24 +0000 (+0200) Subject: [#1405] out-of-pool is also in-subnet X-Git-Tag: Kea-1.9.2~114 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ca4ae11a79e610fa1ba10c9df4a5d7a862acaaac;p=thirdparty%2Fkea.git [#1405] out-of-pool is also in-subnet --- diff --git a/src/bin/dhcp4/dhcp4_messages.mes b/src/bin/dhcp4/dhcp4_messages.mes index cb1c4d33d8..1c4b7785ff 100644 --- a/src/bin/dhcp4/dhcp4_messages.mes +++ b/src/bin/dhcp4/dhcp4_messages.mes @@ -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. diff --git a/src/bin/dhcp4/json_config_parser.cc b/src/bin/dhcp4/json_config_parser.cc index 199b06c301..95a586705b 100644 --- a/src/bin/dhcp4/json_config_parser.cc +++ b/src/bin/dhcp4/json_config_parser.cc @@ -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'" diff --git a/src/bin/dhcp6/dhcp6_messages.mes b/src/bin/dhcp6/dhcp6_messages.mes index e275ae5da9..2dd4dfb2f8 100644 --- a/src/bin/dhcp6/dhcp6_messages.mes +++ b/src/bin/dhcp6/dhcp6_messages.mes @@ -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. diff --git a/src/bin/dhcp6/json_config_parser.cc b/src/bin/dhcp6/json_config_parser.cc index 6af3c0c3ca..c38447dd8a 100644 --- a/src/bin/dhcp6/json_config_parser.cc +++ b/src/bin/dhcp6/json_config_parser.cc @@ -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'" diff --git a/src/lib/dhcpsrv/alloc_engine.cc b/src/lib/dhcpsrv/alloc_engine.cc index 2d91186cc1..6e20d4a1c0 100644 --- a/src/lib/dhcpsrv/alloc_engine.cc +++ b/src/lib/dhcpsrv/alloc_engine.cc @@ -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); } diff --git a/src/lib/dhcpsrv/network.cc b/src/lib/dhcpsrv/network.cc index 26e27e3c35..08e65f673a 100644 --- a/src/lib/dhcpsrv/network.cc +++ b/src/lib/dhcpsrv/network.cc @@ -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) { diff --git a/src/lib/dhcpsrv/parsers/reservation_modes_parser.cc b/src/lib/dhcpsrv/parsers/reservation_modes_parser.cc index fcde1bbfa6..fecb0757da 100644 --- a/src/lib/dhcpsrv/parsers/reservation_modes_parser.cc +++ b/src/lib/dhcpsrv/parsers/reservation_modes_parser.cc @@ -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) {